aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Shields <simon@lineageos.org>2017-04-04 19:05:28 +1000
committerDan Pasanen <dan.pasanen@gmail.com>2017-04-04 09:36:37 -0500
commita17ff1d7e2ac871e17a9f77aff0a1930d1bbf373 (patch)
tree3ea819fa680c6054ae126b833db3ad1449d39dc9
parentc31cf84871831c1881d9525f48f0bc52f61fee11 (diff)
parent37392ec092a43a2f66f192b54895769d8f6ce09d (diff)
downloadandroid_frameworks_opt_telephony-a17ff1d7e2ac871e17a9f77aff0a1930d1bbf373.tar.gz
android_frameworks_opt_telephony-a17ff1d7e2ac871e17a9f77aff0a1930d1bbf373.tar.bz2
android_frameworks_opt_telephony-a17ff1d7e2ac871e17a9f77aff0a1930d1bbf373.zip
Merge tag 'android-7.1.2_r2' into cm-14.1staging/cm-14.1_android-7.1.2_r2
Android 7.1.2 Release 2 (N2G47E) Change-Id: Ic4e01f328b050179df40b25940ea48d8f63c1b03
-rw-r--r--proto/telephony.proto7
-rw-r--r--src/java/com/android/internal/telephony/CallFailCause.java2
-rw-r--r--src/java/com/android/internal/telephony/CallStateException.java1
-rw-r--r--src/java/com/android/internal/telephony/CarrierServiceStateTracker.java192
-rwxr-xr-xsrc/java/com/android/internal/telephony/GsmCdmaCallTracker.java55
-rw-r--r--src/java/com/android/internal/telephony/GsmCdmaConnection.java4
-rw-r--r--src/java/com/android/internal/telephony/GsmCdmaPhone.java21
-rw-r--r--src/java/com/android/internal/telephony/InboundSmsHandler.java48
-rw-r--r--src/java/com/android/internal/telephony/InboundSmsTracker.java37
-rw-r--r--src/java/com/android/internal/telephony/Phone.java44
-rw-r--r--src/java/com/android/internal/telephony/RIL.java8
-rw-r--r--src/java/com/android/internal/telephony/ServiceStateTracker.java82
-rw-r--r--src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java3
-rw-r--r--src/java/com/android/internal/telephony/TelephonyComponentFactory.java11
-rw-r--r--src/java/com/android/internal/telephony/TelephonyTester.java42
-rw-r--r--src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java12
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/ApnSetting.java104
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DcTracker.java141
-rw-r--r--src/java/com/android/internal/telephony/gsm/GsmMmiCode.java12
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhone.java2
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java74
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java93
-rw-r--r--src/java/com/android/internal/telephony/metrics/CallSessionEventBuilder.java6
-rw-r--r--src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java129
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccConstants.java57
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccFileHandler.java8
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccIoResult.java145
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccRecords.java40
-rw-r--r--src/java/com/android/internal/telephony/uicc/IccUtils.java23
-rw-r--r--src/java/com/android/internal/telephony/uicc/PlmnActRecord.java144
-rw-r--r--src/java/com/android/internal/telephony/uicc/SIMFileHandler.java2
-rw-r--r--src/java/com/android/internal/telephony/uicc/SIMRecords.java179
-rw-r--r--src/java/com/android/internal/telephony/uicc/UsimFileHandler.java9
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/FakeSmsContentProvider.java3
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java15
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java5
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java2
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java140
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java69
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java4
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java23
41 files changed, 1629 insertions, 369 deletions
diff --git a/proto/telephony.proto b/proto/telephony.proto
index 066375953..70d210bb3 100644
--- a/proto/telephony.proto
+++ b/proto/telephony.proto
@@ -1018,6 +1018,13 @@ message TelephonyCallSession {
optional CallState state = 2;
optional Type type = 3;
+
+ // For possible values for a call end reason check
+ // frameworks/base/telephony/java/android/telephony/DisconnectCause.java
+ optional int32 call_end_reason = 4;
+
+ // This field is true for Conference Calls
+ optional bool is_multiparty = 5;
}
// Single Radio Voice Call Continuity(SRVCC) progress state
diff --git a/src/java/com/android/internal/telephony/CallFailCause.java b/src/java/com/android/internal/telephony/CallFailCause.java
index 4197bd248..dd3938206 100644
--- a/src/java/com/android/internal/telephony/CallFailCause.java
+++ b/src/java/com/android/internal/telephony/CallFailCause.java
@@ -31,6 +31,7 @@ public interface CallFailCause {
// Unassigned/Unobtainable number
int UNOBTAINABLE_NUMBER = 1;
+ int OPERATOR_DETERMINED_BARRING = 8;
int NORMAL_CLEARING = 16;
// Busy Tone
int USER_BUSY = 17;
@@ -61,7 +62,6 @@ public interface CallFailCause {
// Supplementary
int NO_ROUTE_TO_DESTINAON = 3;
int CHANNEL_UNACCEPTABLE = 6;
- int OPERATOR_DETERMINED_BARRING = 8;
int CALL_FAIL_NO_USER_RESPONDING = 18;
int CALL_FAIL_NO_ANSWER_FROM_USER = 19;
int CALL_REJECTED = 21;
diff --git a/src/java/com/android/internal/telephony/CallStateException.java b/src/java/com/android/internal/telephony/CallStateException.java
index 57cbeb852..cac701a70 100644
--- a/src/java/com/android/internal/telephony/CallStateException.java
+++ b/src/java/com/android/internal/telephony/CallStateException.java
@@ -27,6 +27,7 @@ public class CallStateException extends Exception
public static final int ERROR_INVALID = -1;
public static final int ERROR_DISCONNECTED = 1;
+ public static final int ERROR_POWER_OFF = 2;
public
CallStateException()
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
new file mode 100644
index 000000000..735bfe2ea
--- /dev/null
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.app.PendingIntent;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.Rlog;
+
+/**
+ * This contains Carrier specific logic based on the states/events
+ * managed in ServiceStateTracker.
+ * {@hide}
+ */
+public class CarrierServiceStateTracker extends Handler {
+ private static final String LOG_TAG = "CSST";
+ protected static final int CARRIER_EVENT_BASE = 100;
+ protected static final int CARRIER_EVENT_VOICE_REGISTRATION = CARRIER_EVENT_BASE + 1;
+ protected static final int CARRIER_EVENT_VOICE_DEREGISTRATION = CARRIER_EVENT_BASE + 2;
+ protected static final int CARRIER_EVENT_DATA_REGISTRATION = CARRIER_EVENT_BASE + 3;
+ protected static final int CARRIER_EVENT_DATA_DEREGISTRATION = CARRIER_EVENT_BASE + 4;
+ private static final int SHOW_NOTIFICATION = 200;
+ private static final int NOTIFICATION_ID = 1000;
+ private static final int UNINITIALIZED_DELAY_VALUE = -1;
+ private int mDelay = UNINITIALIZED_DELAY_VALUE;
+ private Phone mPhone;
+ private boolean mIsPhoneRegistered = false;
+ private ServiceStateTracker mSST;
+
+ public CarrierServiceStateTracker(Phone phone, ServiceStateTracker sst) {
+ this.mPhone = phone;
+ this.mSST = sst;
+ phone.getContext().registerReceiver(mBroadcastReceiver, new IntentFilter(
+ CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case CARRIER_EVENT_VOICE_REGISTRATION:
+ case CARRIER_EVENT_DATA_REGISTRATION:
+ mIsPhoneRegistered = true;
+ handleConfigChanges();
+ break;
+ case CARRIER_EVENT_VOICE_DEREGISTRATION:
+ case CARRIER_EVENT_DATA_DEREGISTRATION:
+ if (isGlobalModeOrRadioOffOrAirplaneMode()) {
+ break;
+ }
+ mIsPhoneRegistered = false;
+ handleConfigChanges();
+ break;
+ case SHOW_NOTIFICATION:
+ sendNotification();
+ break;
+ }
+ }
+
+ /**
+ * Returns true if the preferred network is set to 'Global' or the radio is off or in
+ * Airplane Mode else returns false.
+ */
+ private boolean isGlobalModeOrRadioOffOrAirplaneMode() {
+ Context context = mPhone.getContext();
+ int preferredNetworkSetting = -1;
+ int airplaneMode = -1;
+ int subId = mPhone.getSubId();
+ try {
+ preferredNetworkSetting =
+ android.provider.Settings.Global.getInt(context.getContentResolver(),
+ android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId,
+ Phone.PREFERRED_NT_MODE);
+ airplaneMode = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0);
+ } catch (Exception e) {
+ Rlog.e(LOG_TAG, "Unable to get PREFERRED_NETWORK_MODE.");
+ return true;
+ }
+ return ((preferredNetworkSetting == RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA) ||
+ !mSST.isRadioOn() || (airplaneMode != 0));
+ }
+
+ /**
+ * Contains logic to decide when to create/cancel notifications.
+ */
+ private void handleConfigChanges() {
+
+ if (mDelay == UNINITIALIZED_DELAY_VALUE) {
+ cancelNotification();
+ return;
+ }
+ // send a notification if the device is registerd to a network.
+ if (mIsPhoneRegistered) {
+ cancelNotification();
+ Rlog.i(LOG_TAG, "canceling all notifications. ");
+ } else {
+ Message notificationMsg;
+ notificationMsg = obtainMessage(SHOW_NOTIFICATION, null);
+ Rlog.i(LOG_TAG, "starting timer for notifications. ");
+ sendMessageDelayed(notificationMsg, mDelay);
+ }
+ }
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
+ context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ PersistableBundle b = carrierConfigManager.getConfig();
+ mDelay = b.getInt(CarrierConfigManager.KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT);
+ Rlog.i(LOG_TAG, "reading time to delay notification: " + mDelay);
+ handleConfigChanges();
+ }
+ };
+
+ /**
+ * Post a notification to the NotificationManager for changing network type.
+ */
+ private void sendNotification() {
+ Context context = mPhone.getContext();
+
+ Rlog.i(LOG_TAG, "w/values: " + "," + mIsPhoneRegistered + "," + mDelay
+ + "," + isGlobalModeOrRadioOffOrAirplaneMode() + "," + mSST.isRadioOn());
+
+ // exit if the network preference is set to Global or if the phone is registered.
+ if (isGlobalModeOrRadioOffOrAirplaneMode() || mIsPhoneRegistered) {
+ return;
+ }
+
+ NotificationManager notificationManager = (NotificationManager)
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+
+ Intent notificationIntent = new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS);
+ PendingIntent settingsIntent = PendingIntent.getActivity(context, 0, notificationIntent,
+ PendingIntent.FLAG_ONE_SHOT);
+
+ CharSequence title =
+ context.getText(com.android.internal.R.string.NetworkPreferenceSwitchTitle);
+ CharSequence details =
+ context.getText(com.android.internal.R.string.NetworkPreferenceSwitchSummary);
+
+
+ Notification mNotification = new Notification.Builder(context)
+ .setWhen(System.currentTimeMillis())
+ .setAutoCancel(true)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
+ .setContentTitle(title)
+ .setColor(context.getResources().getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setStyle(new Notification.BigTextStyle().bigText(details))
+ .setContentText(details)
+ .setContentIntent(settingsIntent)
+ .build();
+
+ notificationManager.notify(NOTIFICATION_ID, mNotification);
+ }
+
+ /**
+ * Cancel notifications if a registration is pending or has been sent.
+ */
+ private void cancelNotification() {
+ Context context = mPhone.getContext();
+ mIsPhoneRegistered = true;
+ NotificationManager notificationManager = (NotificationManager)
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.cancel(NOTIFICATION_ID);
+ }
+} \ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 1ed421057..090ea30b9 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -88,6 +88,8 @@ public class GsmCdmaCallTracker extends CallTracker {
public PhoneConstants.State mState = PhoneConstants.State.IDLE;
+ private TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();
+
// Following member variables are for CDMA only
private RegistrantList mCallWaitingRegistrants = new RegistrantList();
private boolean mPendingCallInEcm;
@@ -303,6 +305,8 @@ public class GsmCdmaCallTracker extends CallTracker {
mPendingMO = new GsmCdmaConnection(mPhone, checkForTestEmergencyNumber(dialString),
this, mForegroundCall, isEmergencyCall);
mHangupPendingMO = false;
+ mMetrics.writeRilDial(mPhone.getPhoneId(), mPendingMO, clirMode, uusInfo);
+
if ( mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0
|| mPendingMO.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
@@ -715,7 +719,7 @@ public class GsmCdmaCallTracker extends CallTracker {
}
if (mState != oldState) {
mPhone.notifyPhoneStateChanged();
- TelephonyMetrics.getInstance().writePhoneState(mPhone.getPhoneId(), mState);
+ mMetrics.writePhoneState(mPhone.getPhoneId(), mState);
}
}
@@ -863,9 +867,6 @@ public class GsmCdmaCallTracker extends CallTracker {
// Connection missing in CLCC response that we were
// tracking.
mDroppedDuringPoll.add(conn);
- // Dropped connections are removed from the CallTracker
- // list but kept in the GsmCdmaCall list
- mConnections[i] = null;
} else {
// This case means the RIL has no more active call anymore and
// we need to clean up the foregroundCall and ringingCall.
@@ -892,12 +893,10 @@ public class GsmCdmaCallTracker extends CallTracker {
}
// If emergency call is not going through while dialing
checkAndEnableDataCallAfterEmergencyCallDropped();
-
- // Dropped connections are removed from the CallTracker
- // list but kept in the Call list
- mConnections[i] = null;
-
}
+ // Dropped connections are removed from the CallTracker
+ // list but kept in the Call list
+ mConnections[i] = null;
} else if (conn != null && dc != null && !conn.compareTo(dc) && isPhoneTypeGsm()) {
// Connection in CLCC response does not match what
// we were tracking. Assume dropped call and new call
@@ -987,6 +986,7 @@ public class GsmCdmaCallTracker extends CallTracker {
// clear the "local hangup" and "missed/rejected call"
// cases from the "dropped during poll" list
// These cases need no "last call fail" reason
+ ArrayList<GsmCdmaConnection> locallyDisconnectedConnections = new ArrayList<>();
for (int i = mDroppedDuringPoll.size() - 1; i >= 0 ; i--) {
GsmCdmaConnection conn = mDroppedDuringPoll.get(i);
//CDMA
@@ -1008,11 +1008,13 @@ public class GsmCdmaCallTracker extends CallTracker {
mDroppedDuringPoll.remove(i);
hasAnyCallDisconnected |= conn.onDisconnect(cause);
wasDisconnected = true;
+ locallyDisconnectedConnections.add(conn);
} else if (conn.mCause == DisconnectCause.LOCAL
|| conn.mCause == DisconnectCause.INVALID_NUMBER) {
mDroppedDuringPoll.remove(i);
hasAnyCallDisconnected |= conn.onDisconnect(conn.mCause);
wasDisconnected = true;
+ locallyDisconnectedConnections.add(conn);
}
if (!isPhoneTypeGsm() && wasDisconnected && unknownConnectionAppeared
@@ -1021,6 +1023,9 @@ public class GsmCdmaCallTracker extends CallTracker {
newUnknownConnectionCdma = null;
}
}
+ if (locallyDisconnectedConnections.size() > 0) {
+ mMetrics.writeRilCallList(mPhone.getPhoneId(), locallyDisconnectedConnections);
+ }
/* Disconnect any pending Handover connections */
for (Iterator<Connection> it = mHandoverConnections.iterator();
@@ -1033,6 +1038,7 @@ public class GsmCdmaCallTracker extends CallTracker {
} else {
hoConnection.onDisconnect(DisconnectCause.NOT_VALID);
}
+ // TODO: Do we need to update these hoConnections in Metrics ?
it.remove();
}
@@ -1071,6 +1077,7 @@ public class GsmCdmaCallTracker extends CallTracker {
if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) {
mPhone.notifyPreciseCallStateChanged();
+ updateMetrics(mConnections);
}
// If all handover connections are mapped during this poll process clean it up
@@ -1083,6 +1090,14 @@ public class GsmCdmaCallTracker extends CallTracker {
//dumpState();
}
+ private void updateMetrics(GsmCdmaConnection []connections) {
+ ArrayList<GsmCdmaConnection> activeConnections = new ArrayList<>();
+ for(GsmCdmaConnection conn : connections) {
+ if(conn != null) activeConnections.add(conn);
+ }
+ mMetrics.writeRilCallList(mPhone.getPhoneId(), activeConnections);
+ }
+
private void handleRadioNotAvailable() {
// handlePollCalls will clear out its
// call list when it gets the CommandException
@@ -1156,6 +1171,7 @@ public class GsmCdmaCallTracker extends CallTracker {
return;
} else {
try {
+ mMetrics.writeRilHangup(mPhone.getPhoneId(), conn, conn.getGsmCdmaIndex());
mCi.hangupConnection (conn.getGsmCdmaIndex(), obtainCompleteMessage());
} catch (CallStateException ex) {
// Ignore "connection not found"
@@ -1204,6 +1220,7 @@ public class GsmCdmaCallTracker extends CallTracker {
if (call == mRingingCall) {
if (Phone.DEBUG_PHONE) log("(ringing) hangup waiting or background");
+ logHangupEvent(call);
mCi.hangupWaitingOrBackground(obtainCompleteMessage());
} else if (call == mForegroundCall) {
if (call.isDialingOrAlerting()) {
@@ -1217,6 +1234,7 @@ public class GsmCdmaCallTracker extends CallTracker {
log("hangup all conns in active/background call, without affecting ringing call");
hangupAllConnections(call);
} else {
+ logHangupEvent(call);
hangupForegroundResumeBackground();
}
} else if (call == mBackgroundCall) {
@@ -1237,8 +1255,24 @@ public class GsmCdmaCallTracker extends CallTracker {
mPhone.notifyPreciseCallStateChanged();
}
+ private void logHangupEvent(GsmCdmaCall call) {
+ int count = call.mConnections.size();
+ for (int i = 0; i < count; i++) {
+ GsmCdmaConnection cn = (GsmCdmaConnection) call.mConnections.get(i);
+ int call_index;
+ try {
+ call_index = cn.getGsmCdmaIndex();
+ } catch (CallStateException ex) {
+ call_index = -1;
+ }
+ mMetrics.writeRilHangup(mPhone.getPhoneId(), cn, call_index);
+ }
+ if (VDBG) Rlog.v(LOG_TAG, "logHangupEvent logged " + count + " Connections ");
+ }
+
public void hangupWaitingOrBackground() {
if (Phone.DEBUG_PHONE) log("hangupWaitingOrBackground");
+ logHangupEvent(mBackgroundCall);
mCi.hangupWaitingOrBackground(obtainCompleteMessage());
}
@@ -1253,6 +1287,7 @@ public class GsmCdmaCallTracker extends CallTracker {
for (int i = 0; i < count; i++) {
GsmCdmaConnection cn = (GsmCdmaConnection)call.mConnections.get(i);
if (cn.getGsmCdmaIndex() == index) {
+ mMetrics.writeRilHangup(mPhone.getPhoneId(), cn, cn.getGsmCdmaIndex());
mCi.hangupConnection(index, obtainCompleteMessage());
return;
}
@@ -1266,6 +1301,7 @@ public class GsmCdmaCallTracker extends CallTracker {
int count = call.mConnections.size();
for (int i = 0; i < count; i++) {
GsmCdmaConnection cn = (GsmCdmaConnection)call.mConnections.get(i);
+ mMetrics.writeRilHangup(mPhone.getPhoneId(), cn, cn.getGsmCdmaIndex());
mCi.hangupConnection(cn.getGsmCdmaIndex(), obtainCompleteMessage());
}
} catch (CallStateException ex) {
@@ -1422,6 +1458,7 @@ public class GsmCdmaCallTracker extends CallTracker {
updatePhoneState();
mPhone.notifyPreciseCallStateChanged();
+ mMetrics.writeRilCallList(mPhone.getPhoneId(), mDroppedDuringPoll);
mDroppedDuringPoll.clear();
break;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index 28c94c841..364960055 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -446,9 +446,6 @@ public class GsmCdmaConnection extends Connection {
case CallFailCause.CHANNEL_UNACCEPTABLE:
return DisconnectCause.CHANNEL_UNACCEPTABLE;
- case CallFailCause.OPERATOR_DETERMINED_BARRING:
- return DisconnectCause.OPERATOR_DETERMINED_BARRING;
-
case CallFailCause.CALL_FAIL_NO_USER_RESPONDING:
return DisconnectCause.CALL_FAIL_NO_USER_RESPONDING;
@@ -587,6 +584,7 @@ public class GsmCdmaConnection extends Connection {
case CallFailCause.ACM_LIMIT_EXCEEDED:
return DisconnectCause.LIMIT_EXCEEDED;
+ case CallFailCause.OPERATOR_DETERMINED_BARRING:
case CallFailCause.CALL_BARRED:
return DisconnectCause.CALL_BARRED;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 19b14c26a..c9501d453 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -1156,6 +1156,14 @@ public class GsmCdmaPhone extends Phone {
&& mSST.mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE && !isEmergency) {
throw new CallStateException("cannot dial in current state");
}
+ // Check non-emergency voice CS call - shouldn't dial when POWER_OFF
+ if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_POWER_OFF /* CS POWER_OFF */
+ && !VideoProfile.isVideo(videoState) /* voice call */
+ && !isEmergency /* non-emergency call */) {
+ throw new CallStateException(
+ CallStateException.ERROR_POWER_OFF,
+ "cannot dial voice call in airplane mode");
+ }
if (DBG) logd("Trying (non-IMS) CS call");
if (isPhoneTypeGsm()) {
@@ -1938,6 +1946,19 @@ public class GsmCdmaPhone extends Phone {
}
}
+ public boolean supports3gppCallForwardingWhileRoaming() {
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ PersistableBundle b = configManager.getConfig();
+ if (b != null) {
+ return b.getBoolean(
+ CarrierConfigManager.KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
+ } else {
+ // Default value set in CarrierConfigManager
+ return true;
+ }
+ }
+
private void onNetworkInitiatedUssd(MmiCode mmi) {
mMmiCompleteRegistrants.notifyRegistrants(
new AsyncResult(null, mmi, null));
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index e19648f26..71962f8f2 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -79,7 +79,9 @@ import com.android.internal.util.StateMachine;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* This class broadcasts incoming SMS messages to interested apps after storing them in
@@ -114,9 +116,19 @@ public abstract class InboundSmsHandler extends StateMachine {
private static final String[] PDU_SEQUENCE_PORT_PROJECTION = {
"pdu",
"sequence",
- "destination_port"
+ "destination_port",
+ "display_originating_addr"
};
+ /** Mapping from DB COLUMN to PDU_SEQUENCE_PORT PROJECTION index */
+ private static final Map<Integer, Integer> PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING =
+ new HashMap<Integer, Integer>() {{
+ put(PDU_COLUMN, 0);
+ put(SEQUENCE_COLUMN, 1);
+ put(DESTINATION_PORT_COLUMN, 2);
+ put(DISPLAY_ADDRESS_COLUMN, 3);
+ }};
+
public static final int PDU_COLUMN = 0;
public static final int SEQUENCE_COLUMN = 1;
public static final int DESTINATION_PORT_COLUMN = 2;
@@ -126,6 +138,7 @@ public abstract class InboundSmsHandler extends StateMachine {
public static final int ADDRESS_COLUMN = 6;
public static final int ID_COLUMN = 7;
public static final int MESSAGE_BODY_COLUMN = 8;
+ public static final int DISPLAY_ADDRESS_COLUMN = 9;
public static final String SELECT_BY_ID = "_id=?";
public static final String SELECT_BY_REFERENCE = "address=? AND reference_number=? AND " +
@@ -724,7 +737,8 @@ public abstract class InboundSmsHandler extends StateMachine {
tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
sms.getTimestampMillis(), destPort, is3gpp2(), false,
- sms.getDisplayOriginatingAddress(), sms.getMessageBody());
+ sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(),
+ sms.getMessageBody());
} else {
// Create a tracker for this message segment.
SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
@@ -732,7 +746,7 @@ public abstract class InboundSmsHandler extends StateMachine {
int destPort = (portAddrs != null ? portAddrs.destPort : -1);
tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
- sms.getTimestampMillis(), destPort, is3gpp2(),
+ sms.getTimestampMillis(), destPort, is3gpp2(), sms.getOriginatingAddress(),
sms.getDisplayOriginatingAddress(), concatRef.refNumber, concatRef.seqNumber,
concatRef.msgCount, false, sms.getMessageBody());
}
@@ -778,10 +792,12 @@ public abstract class InboundSmsHandler extends StateMachine {
int messageCount = tracker.getMessageCount();
byte[][] pdus;
int destPort = tracker.getDestPort();
+ boolean block = false;
if (messageCount == 1) {
// single-part message
pdus = new byte[][]{tracker.getPdu()};
+ block = BlockChecker.isBlocked(mContext, tracker.getDisplayAddress());
} else {
// multi-part message
Cursor cursor = null;
@@ -810,20 +826,36 @@ public abstract class InboundSmsHandler extends StateMachine {
pdus = new byte[messageCount][];
while (cursor.moveToNext()) {
// subtract offset to convert sequence to 0-based array index
- int index = cursor.getInt(SEQUENCE_COLUMN) - tracker.getIndexOffset();
+ int index = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
+ .get(SEQUENCE_COLUMN)) - tracker.getIndexOffset();
- pdus[index] = HexDump.hexStringToByteArray(cursor.getString(PDU_COLUMN));
+ pdus[index] = HexDump.hexStringToByteArray(cursor.getString(
+ PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING.get(PDU_COLUMN)));
// Read the destination port from the first segment (needed for CDMA WAP PDU).
// It's not a bad idea to prefer the port from the first segment in other cases.
- if (index == 0 && !cursor.isNull(DESTINATION_PORT_COLUMN)) {
- int port = cursor.getInt(DESTINATION_PORT_COLUMN);
+ if (index == 0 && !cursor.isNull(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
+ .get(DESTINATION_PORT_COLUMN))) {
+ int port = cursor.getInt(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
+ .get(DESTINATION_PORT_COLUMN));
// strip format flags and convert to real port number, or -1
port = InboundSmsTracker.getRealDestPort(port);
if (port != -1) {
destPort = port;
}
}
+ // check if display address should be blocked or not
+ if (!block) {
+ // Depending on the nature of the gateway, the display origination address
+ // is either derived from the content of the SMS TP-OA field, or the TP-OA
+ // field contains a generic gateway address and the from address is added
+ // at the beginning in the message body. In that case only the first SMS
+ // (part of Multi-SMS) comes with the display originating address which
+ // could be used for block checking purpose.
+ block = BlockChecker.isBlocked(mContext,
+ cursor.getString(PDU_SEQUENCE_PORT_PROJECTION_INDEX_MAPPING
+ .get(DISPLAY_ADDRESS_COLUMN)));
+ }
}
} catch (SQLException e) {
loge("Can't access multipart SMS database", e);
@@ -877,7 +909,7 @@ public abstract class InboundSmsHandler extends StateMachine {
}
}
- if (BlockChecker.isBlocked(mContext, tracker.getAddress())) {
+ if (block) {
deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs(),
DELETE_PERMANENTLY);
return false;
diff --git a/src/java/com/android/internal/telephony/InboundSmsTracker.java b/src/java/com/android/internal/telephony/InboundSmsTracker.java
index 89ea681b7..9db83ab38 100644
--- a/src/java/com/android/internal/telephony/InboundSmsTracker.java
+++ b/src/java/com/android/internal/telephony/InboundSmsTracker.java
@@ -38,10 +38,9 @@ public class InboundSmsTracker {
private final boolean mIs3gpp2;
private final boolean mIs3gpp2WapPdu;
private final String mMessageBody;
- // Copied from SmsMessageBase#getDisplayOriginatingAddress used for blocking messages.
- private final String mAddress;
// Fields for concatenating multi-part SMS messages
+ private final String mAddress;
private final int mReferenceNumber;
private final int mSequenceNumber;
private final int mMessageCount;
@@ -50,6 +49,16 @@ public class InboundSmsTracker {
private String mDeleteWhere;
private String[] mDeleteWhereArgs;
+ /**
+ * Copied from SmsMessageBase#getDisplayOriginatingAddress used for blocking messages.
+ * DisplayAddress could be email address if this message was from an email gateway, otherwise
+ * same as mAddress. Email gateway might set a generic gateway address as the mAddress which
+ * could not be used for blocking check and append the display email address at the beginning
+ * of the message body. In that case, display email address is only available for the first SMS
+ * in the Multi-part SMS.
+ */
+ private final String mDisplayAddress;
+
/** Destination port flag bit for no destination port. */
private static final int DEST_PORT_FLAG_NO_PORT = (1 << 16);
@@ -73,10 +82,12 @@ public class InboundSmsTracker {
* @param destPort the destination port
* @param is3gpp2 true for 3GPP2 format; false for 3GPP format
* @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
- * @param address originating address, or email if this message was from an email gateway
+ * @param address originating address
+ * @param displayAddress email address if this message was from an email gateway, otherwise same
+ * as originating address
*/
public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
- boolean is3gpp2WapPdu, String address, String messageBody) {
+ boolean is3gpp2WapPdu, String address, String displayAddress, String messageBody) {
mPdu = pdu;
mTimestamp = timestamp;
mDestPort = destPort;
@@ -84,6 +95,7 @@ public class InboundSmsTracker {
mIs3gpp2WapPdu = is3gpp2WapPdu;
mMessageBody = messageBody;
mAddress = address;
+ mDisplayAddress = displayAddress;
// fields for multi-part SMS
mReferenceNumber = -1;
mSequenceNumber = getIndexOffset(); // 0 or 1, depending on type
@@ -102,22 +114,26 @@ public class InboundSmsTracker {
* @param destPort the destination port
* @param is3gpp2 true for 3GPP2 format; false for 3GPP format
* @param address originating address, or email if this message was from an email gateway
+ * @param displayAddress email address if this message was from an email gateway, otherwise same
+ * as originating address
* @param referenceNumber the concatenated reference number
* @param sequenceNumber the sequence number of this segment (0-based)
* @param messageCount the total number of segments
* @param is3gpp2WapPdu true for 3GPP2 format WAP PDU; false otherwise
*/
public InboundSmsTracker(byte[] pdu, long timestamp, int destPort, boolean is3gpp2,
- String address, int referenceNumber, int sequenceNumber, int messageCount,
- boolean is3gpp2WapPdu, String messageBody) {
+ String address, String displayAddress, int referenceNumber, int sequenceNumber,
+ int messageCount, boolean is3gpp2WapPdu, String messageBody) {
mPdu = pdu;
mTimestamp = timestamp;
mDestPort = destPort;
mIs3gpp2 = is3gpp2;
mIs3gpp2WapPdu = is3gpp2WapPdu;
mMessageBody = messageBody;
- mAddress = address;
+ // fields used for check blocking message
+ mDisplayAddress = displayAddress;
// fields for multi-part SMS
+ mAddress = address;
mReferenceNumber = referenceNumber;
mSequenceNumber = sequenceNumber;
mMessageCount = messageCount;
@@ -150,6 +166,7 @@ public class InboundSmsTracker {
mTimestamp = cursor.getLong(InboundSmsHandler.DATE_COLUMN);
mAddress = cursor.getString(InboundSmsHandler.ADDRESS_COLUMN);
+ mDisplayAddress = cursor.getString(InboundSmsHandler.DISPLAY_ADDRESS_COLUMN);
if (cursor.isNull(InboundSmsHandler.COUNT_COLUMN)) {
// single-part message
@@ -203,6 +220,7 @@ public class InboundSmsTracker {
values.put("destination_port", destPort);
if (mAddress != null) {
values.put("address", mAddress);
+ values.put("display_originating_addr", mDisplayAddress);
values.put("reference_number", mReferenceNumber);
values.put("sequence", mSequenceNumber);
values.put("count", mMessageCount);
@@ -241,6 +259,7 @@ public class InboundSmsTracker {
builder.append(" is3gpp2=").append(mIs3gpp2);
if (mAddress != null) {
builder.append(" address=").append(mAddress);
+ builder.append(" display_originating_addr=").append(mDisplayAddress);
builder.append(" refNumber=").append(mReferenceNumber);
builder.append(" seqNumber=").append(mSequenceNumber);
builder.append(" msgCount=").append(mMessageCount);
@@ -287,6 +306,10 @@ public class InboundSmsTracker {
return mAddress;
}
+ public String getDisplayAddress() {
+ return mDisplayAddress;
+ }
+
public String getMessageBody() {
return mMessageBody;
}
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index e6168cde5..7f0b1b804 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -51,10 +51,12 @@ import android.telephony.TelephonyManager;
import android.telephony.VoLteServiceState;
import android.text.TextUtils;
+import com.android.ims.ImsCall;
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.internal.R;
import com.android.internal.telephony.dataconnection.DcTracker;
+import com.android.internal.telephony.imsphone.ImsPhoneCall;
import com.android.internal.telephony.test.SimulatedRadioControl;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
import com.android.internal.telephony.uicc.IccFileHandler;
@@ -2134,23 +2136,40 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
return videoState;
}
- private boolean isVideoCall(Call call) {
- int videoState = getVideoState(call);
- return (VideoProfile.isVideo(videoState));
+ /**
+ * Determines if the specified call currently is or was at some point a video call, or if it is
+ * a conference call.
+ * @param call The call.
+ * @return {@code true} if the call is or was a video call or is a conference call,
+ * {@code false} otherwise.
+ */
+ private boolean isVideoCallOrConference(Call call) {
+ if (call.isMultiparty()) {
+ return true;
+ }
+
+ boolean isDowngradedVideoCall = false;
+ if (call instanceof ImsPhoneCall) {
+ ImsPhoneCall imsPhoneCall = (ImsPhoneCall) call;
+ ImsCall imsCall = imsPhoneCall.getImsCall();
+ return imsCall != null && (imsCall.isVideoCall() ||
+ imsCall.wasVideoCall());
+ }
+ return isDowngradedVideoCall;
}
/**
- * @return {@code true} if video call is present, false otherwise.
+ * @return {@code true} if an IMS video call or IMS conference is present, false otherwise.
*/
- public boolean isVideoCallPresent() {
- boolean isVideoCallActive = false;
+ public boolean isImsVideoCallOrConferencePresent() {
+ boolean isPresent = false;
if (mImsPhone != null) {
- isVideoCallActive = isVideoCall(mImsPhone.getForegroundCall()) ||
- isVideoCall(mImsPhone.getBackgroundCall()) ||
- isVideoCall(mImsPhone.getRingingCall());
+ isPresent = isVideoCallOrConference(mImsPhone.getForegroundCall()) ||
+ isVideoCallOrConference(mImsPhone.getBackgroundCall()) ||
+ isVideoCallOrConference(mImsPhone.getRingingCall());
}
- Rlog.d(LOG_TAG, "isVideoCallActive: " + isVideoCallActive);
- return isVideoCallActive;
+ Rlog.d(LOG_TAG, "isImsVideoCallOrConferencePresent: " + isPresent);
+ return isPresent;
}
/**
@@ -2926,6 +2945,9 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
* Return if UT capability of ImsPhone is enabled or not
*/
public boolean isUtEnabled() {
+ if (mImsPhone != null) {
+ return mImsPhone.isUtEnabled();
+ }
return false;
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 68bf12e2e..410146353 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -1089,8 +1089,6 @@ public class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- mMetrics.writeRilDial(mInstanceId, rr.mSerial, clirMode, uusInfo);
-
send(rr);
}
@@ -1149,8 +1147,6 @@ public class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " +
gsmIndex);
- mMetrics.writeRilHangup(mInstanceId, rr.mSerial, gsmIndex);
-
rr.mParcel.writeInt(1);
rr.mParcel.writeInt(gsmIndex);
@@ -1165,8 +1161,6 @@ public class RIL extends BaseCommands implements CommandsInterface {
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- mMetrics.writeRilHangup(mInstanceId, rr.mSerial, -1);
-
send(rr);
}
@@ -1179,8 +1173,6 @@ public class RIL extends BaseCommands implements CommandsInterface {
result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
- mMetrics.writeRilHangup(mInstanceId, rr.mSerial, -1);
-
send(rr);
}
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 12f5d4e45..abbc1f74c 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -155,6 +155,7 @@ public class ServiceStateTracker extends Handler {
protected RegistrantList mDetachedRegistrants = new RegistrantList();
private RegistrantList mDataRegStateOrRatChangedRegistrants = new RegistrantList();
private RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
+ private RegistrantList mNetworkDetachedRegistrants = new RegistrantList();
private RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
private RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
@@ -284,6 +285,7 @@ public class ServiceStateTracker extends Handler {
private final LocalLog mAttachLog = new LocalLog(10);
private final LocalLog mPhoneTypeLog = new LocalLog(10);
private final LocalLog mRatLog = new LocalLog(20);
+ private final LocalLog mRadioPowerLog = new LocalLog(20);
private class SstSubscriptionsChangedListener extends OnSubscriptionsChangedListener {
public final AtomicInteger mPreviousSubId =
@@ -423,6 +425,8 @@ public class ServiceStateTracker extends Handler {
private boolean mStartedGprsRegCheck;
/** Already sent the event-log for no gprs register. */
private boolean mReportedGprsNoReg;
+
+ private CarrierServiceStateTracker mCSST;
/**
* The Notification object given to the NotificationManager.
*/
@@ -528,6 +532,9 @@ public class ServiceStateTracker extends Handler {
int enableCellularOnBoot = Settings.Global.getInt(mCr,
Settings.Global.ENABLE_CELLULAR_ON_BOOT, 1);
mDesiredPowerState = (enableCellularOnBoot > 0) && ! (airplaneMode > 0);
+ mRadioPowerLog.log("init : airplane mode = " + airplaneMode + " enableCellularOnBoot = " +
+ enableCellularOnBoot);
+
mCr.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true,
@@ -549,6 +556,17 @@ public class ServiceStateTracker extends Handler {
mPhone.notifyOtaspChanged(OTASP_UNINITIALIZED);
updatePhoneType();
+
+ mCSST = new CarrierServiceStateTracker(phone, this);
+
+ registerForNetworkAttached(mCSST,
+ CarrierServiceStateTracker.CARRIER_EVENT_VOICE_REGISTRATION, null);
+ registerForNetworkDetached(mCSST,
+ CarrierServiceStateTracker.CARRIER_EVENT_VOICE_DEREGISTRATION, null);
+ registerForDataConnectionAttached(mCSST,
+ CarrierServiceStateTracker.CARRIER_EVENT_DATA_REGISTRATION, null);
+ registerForDataConnectionDetached(mCSST,
+ CarrierServiceStateTracker.CARRIER_EVENT_DATA_DEREGISTRATION, null);
}
@VisibleForTesting
@@ -2337,12 +2355,14 @@ public class ServiceStateTracker extends Handler {
protected void setPowerStateToDesired() {
if (DBG) {
- log("mDeviceShuttingDown=" + mDeviceShuttingDown +
+ String tmpLog = "mDeviceShuttingDown=" + mDeviceShuttingDown +
", mDesiredPowerState=" + mDesiredPowerState +
", getRadioState=" + mCi.getRadioState() +
", mPowerOffDelayNeed=" + mPowerOffDelayNeed +
", mAlarmSwitch=" + mAlarmSwitch +
- ", mRadioDisabledByCarrier=" + mRadioDisabledByCarrier);
+ ", mRadioDisabledByCarrier=" + mRadioDisabledByCarrier;
+ log(tmpLog);
+ mRadioPowerLog.log(tmpLog);
}
if (mPhone.isPhoneTypeGsm() && mAlarmSwitch) {
@@ -2720,6 +2740,10 @@ public class ServiceStateTracker extends Handler {
mNitzUpdatedTime = false;
}
+ if (hasDeregistered) {
+ mNetworkDetachedRegistrants.notifyRegistrants();
+ }
+
if (hasChanged) {
String operatorNumeric;
@@ -2878,6 +2902,10 @@ public class ServiceStateTracker extends Handler {
mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE
&& mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
+ boolean hasDeregistered =
+ mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
+ && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
+
boolean hasCdmaDataConnectionAttached =
mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE
&& mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
@@ -2952,6 +2980,10 @@ public class ServiceStateTracker extends Handler {
mNetworkAttachedRegistrants.notifyRegistrants();
}
+ if (hasDeregistered) {
+ mNetworkDetachedRegistrants.notifyRegistrants();
+ }
+
if (hasChanged) {
updateSpnDisplay();
@@ -3191,6 +3223,10 @@ public class ServiceStateTracker extends Handler {
mNetworkAttachedRegistrants.notifyRegistrants();
}
+ if (hasDeregistered) {
+ mNetworkDetachedRegistrants.notifyRegistrants();
+ }
+
if (hasChanged) {
updateSpnDisplay();
@@ -4304,11 +4340,31 @@ public class ServiceStateTracker extends Handler {
r.notifyRegistrant();
}
}
+
public void unregisterForNetworkAttached(Handler h) {
mNetworkAttachedRegistrants.remove(h);
}
/**
+ * Registration point for transition into network detached.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj in Message.obj
+ */
+ public void registerForNetworkDetached(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+
+ mNetworkDetachedRegistrants.add(r);
+ if (mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE) {
+ r.notifyRegistrant();
+ }
+ }
+
+ public void unregisterForNetworkDetached(Handler h) {
+ mNetworkDetachedRegistrants.remove(h);
+ }
+
+ /**
* Registration point for transition into packet service restricted zone.
* @param h handler to notify
* @param what what code of message when delivered
@@ -4676,6 +4732,21 @@ public class ServiceStateTracker extends Handler {
}
}
+ private void dumpCellInfoList(PrintWriter pw) {
+ pw.print(" mLastCellInfoList={");
+ if(mLastCellInfoList != null) {
+ boolean first = true;
+ for(CellInfo info : mLastCellInfoList) {
+ if(first == false) {
+ pw.print(",");
+ }
+ first = false;
+ pw.print(info.toString());
+ }
+ }
+ pw.println("}");
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("ServiceStateTracker:");
pw.println(" mSubId=" + mSubId);
@@ -4695,6 +4766,8 @@ public class ServiceStateTracker extends Handler {
pw.println(" mCellLoc=" + mCellLoc);
pw.println(" mNewCellLoc=" + mNewCellLoc);
pw.println(" mLastCellInfoListTime=" + mLastCellInfoListTime);
+ dumpCellInfoList(pw);
+ pw.flush();
pw.println(" mPreferredNetworkType=" + mPreferredNetworkType);
pw.println(" mMaxDataCalls=" + mMaxDataCalls);
pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls);
@@ -4768,6 +4841,11 @@ public class ServiceStateTracker extends Handler {
ipw.increaseIndent();
mRatLog.dump(fd, ipw, args);
ipw.decreaseIndent();
+
+ ipw.println(" Radio power Log:");
+ ipw.increaseIndent();
+ mRadioPowerLog.dump(fd, ipw, args);
+ ipw.decreaseIndent();
}
public boolean isImsRegistered() {
diff --git a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
index dde4d2db5..7f87e43f2 100644
--- a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
+++ b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
@@ -60,7 +60,8 @@ public class SmsBroadcastUndelivered {
"count",
"address",
"_id",
- "message_body"
+ "message_body",
+ "display_originating_addr"
};
private static SmsBroadcastUndelivered instance;
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 7c12c522e..c15402c52 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -140,21 +140,22 @@ public class TelephonyComponentFactory {
* Create a tracker for a single-part SMS.
*/
public InboundSmsTracker makeInboundSmsTracker(byte[] pdu, long timestamp, int destPort,
- boolean is3gpp2, boolean is3gpp2WapPdu, String address, String messageBody) {
+ boolean is3gpp2, boolean is3gpp2WapPdu, String address, String displayAddr,
+ String messageBody) {
Rlog.d(LOG_TAG, "makeInboundSmsTracker");
return new InboundSmsTracker(pdu, timestamp, destPort, is3gpp2, is3gpp2WapPdu, address,
- messageBody);
+ displayAddr, messageBody);
}
/**
* Create a tracker for a multi-part SMS.
*/
public InboundSmsTracker makeInboundSmsTracker(byte[] pdu, long timestamp, int destPort,
- boolean is3gpp2, String address, int referenceNumber, int sequenceNumber,
+ boolean is3gpp2, String address, String displayAddr, int referenceNumber, int sequenceNumber,
int messageCount, boolean is3gpp2WapPdu, String messageBody) {
Rlog.d(LOG_TAG, "makeInboundSmsTracker");
- return new InboundSmsTracker(pdu, timestamp, destPort, is3gpp2, address, referenceNumber,
- sequenceNumber, messageCount, is3gpp2WapPdu, messageBody);
+ return new InboundSmsTracker(pdu, timestamp, destPort, is3gpp2, address, displayAddr,
+ referenceNumber, sequenceNumber, messageCount, is3gpp2WapPdu, messageBody);
}
/**
diff --git a/src/java/com/android/internal/telephony/TelephonyTester.java b/src/java/com/android/internal/telephony/TelephonyTester.java
index ba59e6d33..3de356fa9 100644
--- a/src/java/com/android/internal/telephony/TelephonyTester.java
+++ b/src/java/com/android/internal/telephony/TelephonyTester.java
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
+import android.os.BadParcelableException;
import android.os.Build;
import android.preference.PreferenceManager;
import android.telephony.Rlog;
@@ -92,24 +93,29 @@ public class TelephonyTester {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (DBG) log("sIntentReceiver.onReceive: action=" + action);
- if (action.equals(mPhone.getActionDetached())) {
- log("simulate detaching");
- mPhone.getServiceStateTracker().mDetachedRegistrants.notifyRegistrants();
- } else if (action.equals(mPhone.getActionAttached())) {
- log("simulate attaching");
- mPhone.getServiceStateTracker().mAttachedRegistrants.notifyRegistrants();
- } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) {
- log("inject simulated conference event package");
- handleTestConferenceEventPackage(context, intent.getStringExtra(EXTRA_FILENAME));
- } else if (action.equals(ACTION_TEST_DIALOG_EVENT_PACKAGE)) {
- log("handle test dialog event package intent");
- handleTestDialogEventPackageIntent(intent);
- } else if (action.equals(ACTION_TEST_HANDOVER_FAIL)) {
- log("handle handover fail test intent");
- handleHandoverFailedIntent();
- } else {
- if (DBG) log("onReceive: unknown action=" + action);
+ try {
+ if (DBG) log("sIntentReceiver.onReceive: action=" + action);
+ if (action.equals(mPhone.getActionDetached())) {
+ log("simulate detaching");
+ mPhone.getServiceStateTracker().mDetachedRegistrants.notifyRegistrants();
+ } else if (action.equals(mPhone.getActionAttached())) {
+ log("simulate attaching");
+ mPhone.getServiceStateTracker().mAttachedRegistrants.notifyRegistrants();
+ } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) {
+ log("inject simulated conference event package");
+ handleTestConferenceEventPackage(context,
+ intent.getStringExtra(EXTRA_FILENAME));
+ } else if (action.equals(ACTION_TEST_DIALOG_EVENT_PACKAGE)) {
+ log("handle test dialog event package intent");
+ handleTestDialogEventPackageIntent(intent);
+ } else if (action.equals(ACTION_TEST_HANDOVER_FAIL)) {
+ log("handle handover fail test intent");
+ handleHandoverFailedIntent();
+ } else {
+ if (DBG) log("onReceive: unknown action=" + action);
+ }
+ } catch (BadParcelableException e) {
+ Rlog.w(LOG_TAG, e);
}
}
};
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
index 0ed4bc413..fbc60d481 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
@@ -174,7 +174,8 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
if (SmsEnvelope.TELESERVICE_WAP == teleService) {
return processCdmaWapPdu(sms.getUserData(), sms.mMessageRef,
- sms.getOriginatingAddress(), sms.getTimestampMillis());
+ sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(),
+ sms.getTimestampMillis());
} else if (SmsEnvelope.TELESERVICE_CT_WAP == teleService) {
/* China Telecom WDP header contains Message identifier
and User data subparametrs extract these fields */
@@ -182,7 +183,8 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
return Intents.RESULT_SMS_HANDLED;
}
return processCdmaWapPdu(sms.getUserData(), sms.mMessageRef,
- sms.getOriginatingAddress(), sms.getTimestampMillis());
+ sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(),
+ sms.getTimestampMillis());
}
return dispatchNormalMessage(smsb);
@@ -269,7 +271,7 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
* {@link Activity#RESULT_OK} if the message has been broadcast
* to applications
*/
- private int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address,
+ private int processCdmaWapPdu(byte[] pdu, int referenceNumber, String address, String dispAddr,
long timestamp) {
int index = 0;
@@ -314,8 +316,8 @@ public class CdmaInboundSmsHandler extends InboundSmsHandler {
System.arraycopy(pdu, index, userData, 0, pdu.length - index);
InboundSmsTracker tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(
- userData, timestamp, destinationPort, true, address, referenceNumber, segment,
- totalSegments, true, HexDump.toHexString(userData));
+ userData, timestamp, destinationPort, true, address, dispAddr, referenceNumber,
+ segment, totalSegments, true, HexDump.toHexString(userData));
// de-duping is done only for text messages
return addTrackerToRawTableAndSendMessage(tracker, false /* don't de-dup */);
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java b/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
index 7e81d750d..3a4049e7c 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
@@ -114,18 +114,6 @@ public class ApnSetting {
* */
public boolean permanentFailed = false;
- /**
- * Metered APN types which would be accounted for in data usage. This is a map of subId ->
- * set of metered apn strings for the carrier.
- */
- private static HashMap<Integer, HashSet<String>> sMeteredApnTypes = new HashMap<>();
-
- /**
- * Metered Roaming APN types which would be accounted for in data usage. This is a map of
- * subId -> set of metered roaming apn strings for the carrier.
- */
- private static HashMap<Integer, HashSet<String>> sMeteredRoamingApnTypes = new HashMap<>();
-
public ApnSetting(int id, String numeric, String carrier, String apn,
String proxy, String port,
String mmsc, String mmsProxy, String mmsPort,
@@ -354,10 +342,12 @@ public class ApnSetting {
public boolean canHandleType(String type) {
if (!carrierEnabled) return false;
+ boolean wildcardable = true;
+ if (PhoneConstants.APN_TYPE_IA.equalsIgnoreCase(type)) wildcardable = false;
for (String t : types) {
// DEFAULT handles all, and HIPRI is handled by DEFAULT
if (t.equalsIgnoreCase(type) ||
- t.equalsIgnoreCase(PhoneConstants.APN_TYPE_ALL) ||
+ (wildcardable && t.equalsIgnoreCase(PhoneConstants.APN_TYPE_ALL)) ||
(t.equalsIgnoreCase(PhoneConstants.APN_TYPE_DEFAULT) &&
type.equalsIgnoreCase(PhoneConstants.APN_TYPE_HIPRI))) {
return true;
@@ -428,64 +418,55 @@ public class ApnSetting {
public static boolean isMeteredApnType(String type, Context context, int subId,
boolean isRoaming) {
- HashMap<Integer, HashSet<String>> meteredApnTypesCache = (isRoaming) ?
- sMeteredApnTypes : sMeteredRoamingApnTypes;
String carrierConfig = (isRoaming) ?
CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS :
CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS;
- synchronized (meteredApnTypesCache) {
- HashSet<String> meteredApnSet = meteredApnTypesCache.get(subId);
-
- // In case of cache miss, we need to look up the settings from carrier config.
- if (meteredApnSet == null) {
- // Retrieve the metered APN types from carrier config
- CarrierConfigManager configManager = (CarrierConfigManager)
- context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- if (configManager == null) {
- Rlog.e(LOG_TAG, "Carrier config service is not available");
- return true;
- }
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager == null) {
+ Rlog.e(LOG_TAG, "Carrier config service is not available");
+ return true;
+ }
- PersistableBundle b = configManager.getConfigForSubId(subId);
- if (b == null) {
- Rlog.e(LOG_TAG, "Can't get the config. subId = " + subId);
- return true;
- }
+ PersistableBundle b = configManager.getConfigForSubId(subId);
+ if (b == null) {
+ Rlog.e(LOG_TAG, "Can't get the config. subId = " + subId);
+ return true;
+ }
- String[] meteredApnTypes = b.getStringArray(carrierConfig);
- if (meteredApnTypes == null) {
- Rlog.e(LOG_TAG, carrierConfig + " is not available. " + "subId = " + subId);
- return true;
- }
+ String[] meteredApnTypes = b.getStringArray(carrierConfig);
+ if (meteredApnTypes == null) {
+ Rlog.e(LOG_TAG, carrierConfig + " is not available. " + "subId = " + subId);
+ return true;
+ }
- meteredApnSet = new HashSet<String>(Arrays.asList(meteredApnTypes));
- meteredApnTypesCache.put(subId, meteredApnSet);
- if (DBG) {
- Rlog.d(LOG_TAG, "For subId = " + subId + ", metered APN types are " +
- Arrays.toString(meteredApnSet.toArray()) +
- " isRoaming: " + isRoaming);
- }
- }
- // If all types of APN are metered, then this APN setting must be metered.
- if (meteredApnSet.contains(PhoneConstants.APN_TYPE_ALL)) {
- if (DBG) Rlog.d(LOG_TAG, "All APN types are metered. isRoaming: " + isRoaming);
- return true;
- }
+ HashSet<String> meteredApnSet = new HashSet<>(Arrays.asList(meteredApnTypes));
+ if (DBG) {
+ Rlog.d(LOG_TAG, "For subId = " + subId + ", metered APN types are " +
+ Arrays.toString(meteredApnSet.toArray()) +
+ " isRoaming: " + isRoaming);
+ }
+
+ // If all types of APN are metered, then this APN setting must be metered.
+ if (meteredApnSet.contains(PhoneConstants.APN_TYPE_ALL)) {
+ if (DBG) Rlog.d(LOG_TAG, "All APN types are metered. isRoaming: " + isRoaming);
+ return true;
+ }
- if (meteredApnSet.contains(type)) {
- if (DBG) Rlog.d(LOG_TAG, type + " is metered. isRoaming: " + isRoaming);
+ if (meteredApnSet.contains(type)) {
+ if (DBG) Rlog.d(LOG_TAG, type + " is metered. isRoaming: " + isRoaming);
+ return true;
+ } else if (type.equals(PhoneConstants.APN_TYPE_ALL)) {
+ // Assuming no configuration error, if at least one APN type is
+ // metered, then this APN setting is metered.
+ if (meteredApnSet.size() > 0) {
+ if (DBG) Rlog.d(LOG_TAG, "APN_TYPE_ALL APN is metered. isRoaming: " +
+ isRoaming);
return true;
- } else if (type.equals(PhoneConstants.APN_TYPE_ALL)) {
- // Assuming no configuration error, if at least one APN type is
- // metered, then this APN setting is metered.
- if (meteredApnSet.size() > 0) {
- if (DBG) Rlog.d(LOG_TAG, "APN_TYPE_ALL APN is metered. isRoaming: " +
- isRoaming);
- return true;
- }
}
}
+
if (DBG) Rlog.d(LOG_TAG, type + " is not metered. isRoaming: " + isRoaming);
return false;
}
@@ -520,7 +501,10 @@ public class ApnSetting {
proxy.equals(other.proxy) &&
mmsc.equals(other.mmsc) &&
mmsProxy.equals(other.mmsProxy) &&
+ TextUtils.equals(mmsPort, other.mmsPort) &&
port.equals(other.port) &&
+ TextUtils.equals(user, other.user) &&
+ TextUtils.equals(password, other.password) &&
authType == other.authType &&
Arrays.deepEquals(types, other.types) &&
protocol.equals(other.protocol) &&
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index cb6f0d90e..2f33d3b46 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -47,6 +47,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
+import android.os.PersistableBundle;
import android.os.RegistrantList;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -56,6 +57,7 @@ import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Telephony;
+import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.PcoData;
import android.telephony.Rlog;
@@ -315,6 +317,14 @@ public class DcTracker extends Handler {
log("WIFI_STATE_CHANGED_ACTION: enabled=" + enabled
+ " mIsWifiConnected=" + mIsWifiConnected);
}
+ } else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
+ CarrierConfigManager configMgr = (CarrierConfigManager)
+ mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configMgr != null) {
+ PersistableBundle cfg = configMgr.getConfigForSubId(mPhone.getSubId());
+ if (cfg != null) mAllowUserEditTetherApn =
+ cfg.getBoolean(CarrierConfigManager.KEY_EDITABLE_TETHER_APN_BOOL);
+ }
} else {
if (DBG) log("onReceive: Unknown action=" + action);
}
@@ -617,6 +627,22 @@ public class DcTracker extends Handler {
private boolean mMeteredApnDisabled = false;
/**
+ * int to remember whether has setDataProfiles and with roaming or not.
+ * 0: default, has never set data profile
+ * 1: has set data profile with home protocol
+ * 2: has set data profile with roaming protocol
+ * This is not needed once RIL command is updated to support both home and roaming protocol.
+ */
+ private int mSetDataProfileStatus = 0;
+
+ /**
+ * Whether carrier allow user edited tether APN. Updated by carrier config
+ * KEY_EDITABLE_TETHER_APN_BOOL
+ * If true, APN with dun type from database will be used, see fetchDunApn for details.
+ */
+ private boolean mAllowUserEditTetherApn = false;
+
+ /**
* Handles changes to the APN db.
*/
private class ApnChangeObserver extends ContentObserver {
@@ -688,6 +714,7 @@ public class DcTracker extends Handler {
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);
// TODO - redundent with update call below?
mDataEnabledSettings.setUserDataEnabled(getDataEnabled());
@@ -1038,6 +1065,7 @@ public class DcTracker extends Handler {
public void onReceive(Context context, Intent intent) {
// Turning back on the radio can take time on the order of a minute, so show user a
// spinner so they know something is going on.
+ log("onReceive : ProvisionNotificationBroadcastReceiver");
mProvisioningSpinner = new ProgressDialog(context);
mProvisioningSpinner.setTitle(mNetworkOperator);
mProvisioningSpinner.setMessage(
@@ -1857,50 +1885,56 @@ public class DcTracker extends Handler {
return null;
}
int bearer = mPhone.getServiceState().getRilDataRadioTechnology();
+ IccRecords r = mIccRecords.get();
+ String operator = (r != null) ? r.getOperatorNumeric() : "";
+ ArrayList<ApnSetting> dunCandidates = new ArrayList<ApnSetting>();
ApnSetting retDunSetting = null;
+
+ // Places to look for tether APN in order: TETHER_DUN_APN setting, APN database if
+ // carrier allows it, and config_tether_apndata resource.
String apnData = Settings.Global.getString(mResolver, Settings.Global.TETHER_DUN_APN);
- List<ApnSetting> dunSettings = ApnSetting.arrayFromString(apnData);
- IccRecords r = mIccRecords.get();
- for (ApnSetting dunSetting : dunSettings) {
- String operator = mPhone.getOperatorNumeric();
- if (!ServiceState.bitmaskHasTech(dunSetting.bearerBitmask, bearer)) continue;
- if (dunSetting.numeric.equals(operator)) {
- if (dunSetting.hasMvnoParams()) {
- if (r != null && ApnSetting.mvnoMatches(r, dunSetting.mvnoType,
- dunSetting.mvnoMatchData)) {
- if (VDBG) {
- log("fetchDunApn: global TETHER_DUN_APN dunSetting=" + dunSetting);
- }
- return dunSetting;
- }
- } else if (mMvnoMatched == false) {
- if (VDBG) log("fetchDunApn: global TETHER_DUN_APN dunSetting=" + dunSetting);
- return dunSetting;
+ if (!TextUtils.isEmpty(apnData)) {
+ dunCandidates.addAll(ApnSetting.arrayFromString(apnData));
+ if (VDBG) log("fetchDunApn: dunCandidates from Setting: " + dunCandidates);
+ } else if (mAllowUserEditTetherApn) {
+ for (ApnSetting apn : mAllApnSettings) {
+ if (apn.canHandleType(PhoneConstants.APN_TYPE_DUN)) {
+ dunCandidates.add(apn);
}
}
+ if (VDBG) log("fetchDunApn: dunCandidates from database: " + dunCandidates);
+ }
+ // If TETHER_DUN_APN isn't set or
+ // mAllowUserEditTetherApn is true but APN database doesn't have dun APN,
+ // try the resource as last resort.
+ if (dunCandidates.isEmpty()) {
+ String[] apnArrayData = mPhone.getContext().getResources()
+ .getStringArray(R.array.config_tether_apndata);
+ for (String apnString : apnArrayData) {
+ ApnSetting apn = ApnSetting.fromString(apnString);
+ // apn may be null if apnString isn't valid or has error parsing
+ if (apn != null) dunCandidates.add(apn);
+ }
+ if (VDBG) log("fetchDunApn: dunCandidates from resource: " + dunCandidates);
}
- Context c = mPhone.getContext();
- String[] apnArrayData = c.getResources().getStringArray(R.array.config_tether_apndata);
- for (String apn : apnArrayData) {
- ApnSetting dunSetting = ApnSetting.fromString(apn);
- if (dunSetting != null) {
- if (!ServiceState.bitmaskHasTech(dunSetting.bearerBitmask, bearer)) continue;
+ for (ApnSetting dunSetting : dunCandidates) {
+ if (!ServiceState.bitmaskHasTech(dunSetting.bearerBitmask, bearer)) continue;
+ if (dunSetting.numeric.equals(operator)) {
if (dunSetting.hasMvnoParams()) {
if (r != null && ApnSetting.mvnoMatches(r, dunSetting.mvnoType,
dunSetting.mvnoMatchData)) {
- if (VDBG) {
- log("fetchDunApn: config_tether_apndata mvno dunSetting=" + dunSetting);
- }
- return dunSetting;
+ retDunSetting = dunSetting;
+ break;
}
} else if (mMvnoMatched == false) {
retDunSetting = dunSetting;
+ break;
}
}
}
- if (VDBG) log("fetchDunApn: config_tether_apndata dunSetting=" + retDunSetting);
+ if (VDBG) log("fetchDunApn: dunSetting=" + retDunSetting);
return retDunSetting;
}
@@ -2183,15 +2217,15 @@ public class DcTracker extends Handler {
log("setInitialApn: E mPreferredApn=" + mPreferredApn);
- if (mAllApnSettings != null && !mAllApnSettings.isEmpty()) {
+ if (mPreferredApn != null && mPreferredApn.canHandleType(PhoneConstants.APN_TYPE_IA)) {
+ iaApnSetting = mPreferredApn;
+ } else if (mAllApnSettings != null && !mAllApnSettings.isEmpty()) {
firstApnSetting = mAllApnSettings.get(0);
log("setInitialApn: firstApnSetting=" + firstApnSetting);
// Search for Initial APN setting and the first apn that can handle default
for (ApnSetting apn : mAllApnSettings) {
- // Can't use apn.canHandleType(), as that returns true for APNs that have no type.
- if (ArrayUtils.contains(apn.types, PhoneConstants.APN_TYPE_IA) &&
- apn.carrierEnabled) {
+ if (apn.canHandleType(PhoneConstants.APN_TYPE_IA)) {
// The Initial Attach APN is highest priority so use it if there is one
log("setInitialApn: iaApnSetting=" + apn);
iaApnSetting = apn;
@@ -2460,6 +2494,10 @@ public class DcTracker extends Handler {
// Tear down all metered apns
cleanUpAllConnections(true, Phone.REASON_CARRIER_ACTION_DISABLE_METERED_APN);
} else {
+ // Re-evauluate Otasp state
+ int otaspState = mPhone.getServiceStateTracker().getOtasp();
+ mPhone.notifyOtaspChanged(otaspState);
+
teardownRestrictedMeteredConnections();
setupDataOnConnectableApns(Phone.REASON_DATA_ENABLED);
}
@@ -2703,6 +2741,16 @@ public class DcTracker extends Handler {
// TODO change our retry manager to use the appropriate numbers for the new APN
if (DBG) log("onEnableApn: apnContext=" + apnContext + " call applyNewState");
applyNewState(apnContext, enabled == DctConstants.ENABLED, apnContext.getDependencyMet());
+
+ if ((enabled == DctConstants.DISABLED) &&
+ isOnlySingleDcAllowed(mPhone.getServiceState().getRilDataRadioTechnology()) &&
+ !isHigherPriorityApnContextActive(apnContext)) {
+
+ if(DBG) log("onEnableApn: isOnlySingleDcAllowed true & higher priority APN disabled");
+ // If the highest priority APN is disabled and only single
+ // data call is allowed, try to setup data call on other connectable APN.
+ setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION);
+ }
}
// TODO: We shouldnt need this.
@@ -2823,6 +2871,10 @@ public class DcTracker extends Handler {
if (!mDataEnabledSettings.isUserDataEnabled()) return;
+ // Note onRoamingOff will be called immediately when DcTracker registerForDataRoamingOff,
+ // and will be called again if SST calls mDataRoamingOffRegistrants.notify().
+ setDataProfilesAsNeeded();
+
if (getDataOnRoamingEnabled() == false) {
notifyOffApnsOfAvailability(Phone.REASON_ROAMING_OFF);
setupDataOnConnectableApns(Phone.REASON_ROAMING_OFF);
@@ -3357,27 +3409,29 @@ public class DcTracker extends Handler {
}
protected void setDataProfilesAsNeeded() {
- if (DBG) log("setDataProfilesAsNeeded");
+ if (DBG) log("setDataProfilesAsNeeded mSetDataProfileStatus: " + mSetDataProfileStatus);
if (mAllApnSettings != null && !mAllApnSettings.isEmpty()) {
ArrayList<DataProfile> dps = new ArrayList<DataProfile>();
+ // Note getDataRoaming is also false if data not registered
+ boolean isRoaming = mPhone.getServiceState().getDataRoaming();
+ // If has set profile with home, and isRoaming is also false, no need to resend
+ // Also skip if has set profile with roaming and isRoaming is true.
+ if ((mSetDataProfileStatus == 1 && !isRoaming) ||
+ (mSetDataProfileStatus == 2 && isRoaming)) {
+ return;
+ }
for (ApnSetting apn : mAllApnSettings) {
if (apn.modemCognitive) {
- DataProfile dp = new DataProfile(apn,
- mPhone.getServiceState().getDataRoaming());
- boolean isDup = false;
- for(DataProfile dpIn : dps) {
- if (dp.equals(dpIn)) {
- isDup = true;
- break;
- }
- }
- if (!isDup) {
+ DataProfile dp = new DataProfile(apn, isRoaming);
+ // ArrayList.contains will call object.equals
+ if (!dps.contains(dp)) {
dps.add(dp);
}
}
}
if(dps.size() > 0) {
mPhone.mCi.setDataProfile(dps.toArray(new DataProfile[0]), null);
+ mSetDataProfileStatus = isRoaming ? 2 : 1;
}
}
}
@@ -4295,6 +4349,7 @@ public class DcTracker extends Handler {
pw.println(" mAutoAttachOnCreation=" + mAutoAttachOnCreation.get());
pw.println(" mIsScreenOn=" + mIsScreenOn);
pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator);
+ pw.println(" mSetDataProfileStatus=" + mSetDataProfileStatus);
pw.flush();
pw.println(" ***************************************");
DcController dcc = mDcc;
diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 30c9f161f..f98e360ad 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -34,7 +34,6 @@ import android.util.Log;
import android.widget.Toast;
import static com.android.internal.telephony.CommandsInterface.*;
-import com.android.internal.telephony.gsm.SsData;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -1254,6 +1253,17 @@ public final class GsmMmiCode extends Handler implements MmiCode {
} else if (err == CommandException.Error.FDN_CHECK_FAILURE) {
Rlog.i(LOG_TAG, "FDN_CHECK_FAILURE");
sb.append(mContext.getText(com.android.internal.R.string.mmiFdnError));
+ } else if (err == CommandException.Error.MODEM_ERR) {
+ // Some carriers do not allow changing call forwarding settings while roaming
+ // and will return an error from the modem.
+ if (isServiceCodeCallForwarding(mSc)
+ && mPhone.getServiceState().getVoiceRoaming()
+ && !mPhone.supports3gppCallForwardingWhileRoaming()) {
+ sb.append(mContext.getText(
+ com.android.internal.R.string.mmiErrorWhileRoaming));
+ } else {
+ sb.append(getErrorMessage(ar));
+ }
} else {
sb.append(getErrorMessage(ar));
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 5514a3b6c..9e711210e 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -844,7 +844,7 @@ public class ImsPhone extends ImsPhoneBase {
dialingNumber,
serviceClass,
timerSeconds,
- onComplete);
+ resp);
} catch (ImsException e) {
sendErrorResponse(onComplete, e);
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index ffb404c61..4c0edb444 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -66,6 +66,7 @@ import com.android.ims.ImsUtInterface;
import com.android.ims.internal.IImsVideoCallProvider;
import com.android.ims.internal.ImsCallSession;
import com.android.ims.internal.ImsVideoCallProviderWrapper;
+import com.android.ims.internal.VideoPauseTracker;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.CallTracker;
@@ -261,6 +262,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
private Call.SrvccState mSrvccState = Call.SrvccState.NONE;
private boolean mIsInEmergencyCall = false;
+ private boolean mIsDataEnabled = false;
private int pendingCallClirMode;
private int mPendingCallVideoState;
@@ -269,6 +271,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
private boolean mSwitchingFgAndBgCalls = false;
private ImsCall mCallExpectedToResume = null;
private boolean mAllowEmergencyVideoCalls = false;
+ private boolean mIgnoreDataEnabledChangedForVideoCalls = false;
private Object mAddParticipantLock = new Object();
private Message mAddPartResp;
@@ -317,6 +320,13 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
private boolean mNotifyHandoverVideoFromWifiToLTE = false;
/**
+ * Carrier configuration option which determines whether the carrier supports the
+ * {@link VideoProfile#STATE_PAUSED} signalling.
+ * See {@link CarrierConfigManager#KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL} for more information.
+ */
+ private boolean mSupportPauseVideo = false;
+
+ /**
* Carrier configuration option which defines a mapping from pairs of
* {@link ImsReasonInfo#getCode()} and {@link ImsReasonInfo#getExtraMessage()} values to a new
* {@code ImsReasonInfo#CODE_*} value.
@@ -325,6 +335,17 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
*/
private Map<Pair<Integer, String>, Integer> mImsReasonCodeMap = new ArrayMap<>();
+ /**
+ * TODO: Remove this code; it is a workaround.
+ * When {@code true}, forces {@link ImsManager#updateImsServiceConfig(Context, int, boolean)} to
+ * be called when an ongoing video call is disconnected. In some cases, where video pause is
+ * supported by the carrier, when {@link #onDataEnabledChanged(boolean, int)} reports that data
+ * has been disabled we will pause the video rather than disconnecting the call. When this
+ * happens we need to prevent the IMS service config from being updated, as this will cause VT
+ * to be disabled mid-call, resulting in an inability to un-pause the video.
+ */
+ private boolean mShouldUpdateImsConfigOnDisconnect = false;
+
//***** Events
@@ -617,6 +638,10 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
CarrierConfigManager.KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL);
mNotifyHandoverVideoFromWifiToLTE = carrierConfig.getBoolean(
CarrierConfigManager.KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL);
+ mIgnoreDataEnabledChangedForVideoCalls = carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
+ mSupportPauseVideo = carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL);
String[] mappings = carrierConfig
.getStringArray(CarrierConfigManager.KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY);
@@ -1719,6 +1744,13 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
mCallExpectedToResume = null;
}
}
+
+ if (mShouldUpdateImsConfigOnDisconnect) {
+ // Ensure we update the IMS config when the call is disconnected; we delayed this
+ // because a video call was paused.
+ ImsManager.updateImsServiceConfig(mPhone.getContext(), mPhone.getPhoneId(), true);
+ mShouldUpdateImsConfigOnDisconnect = false;
+ }
}
@Override
@@ -2261,16 +2293,10 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
mPhone.notifyForVideoCapabilityChanged(isVideoCallEnabled());
}
- // TODO: Use the ImsCallSession or ImsCallProfile to tell the initial Wifi state and
- // {@link ImsCallSession.Listener#callSessionHandover} to listen for changes to
- // wifi capability caused by a handover.
if (DBG) log("onFeatureCapabilityChanged: isVolteEnabled=" + isVolteEnabled()
+ ", isVideoCallEnabled=" + isVideoCallEnabled()
+ ", isVowifiEnabled=" + isVowifiEnabled()
+ ", isUtEnabled=" + isUtEnabled());
- for (ImsPhoneConnection connection : mConnections) {
- connection.updateWifiState();
- }
mPhone.onFeatureCapabilityChanged();
@@ -2825,7 +2851,14 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
private void onDataEnabledChanged(boolean enabled, int reason) {
log("onDataEnabledChanged: enabled=" + enabled + ", reason=" + reason);
+
ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId()).setDataEnabled(enabled);
+ mIsDataEnabled = enabled;
+
+ if (mIgnoreDataEnabledChangedForVideoCalls) {
+ log("Ignore data " + ((enabled) ? "enabled" : "disabled") + " due to carrier policy.");
+ return;
+ }
if (!enabled) {
int reasonCode;
@@ -2858,9 +2891,12 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
TelephonyManager.EVENT_DOWNGRADE_DATA_LIMIT_REACHED, null);
}
modifyVideoCall(imsCall, VideoProfile.STATE_AUDIO_ONLY);
+ } else if (mSupportPauseVideo) {
+ // The carrier supports video pause signalling, so pause the video.
+ mShouldUpdateImsConfigOnDisconnect = true;
+ conn.pauseVideo(VideoPauseTracker.SOURCE_DATA_ENABLED);
} else {
- // If the carrier does not support downgrading to voice, the only choice we
- // have is to terminate the call.
+ // At this point the only choice we have is to terminate the call.
try {
imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED, reasonCode);
} catch (ImsException ie) {
@@ -2869,11 +2905,27 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
}
}
}
+ } else if (mSupportPauseVideo) {
+ // Data was re-enabled, so un-pause previously paused video calls.
+ for (ImsPhoneConnection conn : mConnections) {
+ // If video is paused, check to see if there are any pending pauses due to enabled
+ // state of data changing.
+ log("onDataEnabledChanged - resuming " + conn);
+ if (VideoProfile.isPaused(conn.getVideoState()) &&
+ conn.wasVideoPausedFromSource(VideoPauseTracker.SOURCE_DATA_ENABLED)) {
+ // The data enabled state was a cause of a pending pause, so potentially
+ // resume the video now.
+ conn.resumeVideo(VideoPauseTracker.SOURCE_DATA_ENABLED);
+ }
+ }
+ mShouldUpdateImsConfigOnDisconnect = false;
}
- // This will call into updateVideoCallFeatureValue and eventually all clients will be
- // asynchronously notified that the availability of VT over LTE has changed.
- ImsManager.updateImsServiceConfig(mPhone.getContext(), mPhone.getPhoneId(), true);
+ if (!mShouldUpdateImsConfigOnDisconnect) {
+ // This will call into updateVideoCallFeatureValue and eventually all clients will be
+ // asynchronously notified that the availability of VT over LTE has changed.
+ ImsManager.updateImsServiceConfig(mPhone.getContext(), mPhone.getPhoneId(), true);
+ }
}
/**
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
index 39096f5aa..87e91c78d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -101,15 +101,7 @@ public class ImsPhoneConnection extends Connection implements
*/
private boolean mShouldIgnoreVideoStateChanges = false;
- /**
- * Used to indicate whether the wifi state is based on
- * {@link com.android.ims.ImsConnectionStateListener#
- * onFeatureCapabilityChanged(int, int[], int[])} callbacks, or values received via the
- * {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE} extra. Util we receive a value via the extras,
- * we will use the wifi state based on the {@code onFeatureCapabilityChanged}. Once a value
- * is received via the extras, we will prefer those values going forward.
- */
- private boolean mIsWifiStateFromExtras = false;
+ private ImsVideoCallProviderWrapper mImsVideoCallProviderWrapper;
//***** Event Constants
private static final int EVENT_DTMF_DONE = 1;
@@ -180,8 +172,6 @@ public class ImsPhoneConnection extends Connection implements
mCreateTime = System.currentTimeMillis();
mUusInfo = null;
- updateWifiState();
-
// Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
// in the ImsPhoneConnection. This isn't going to inform any listeners (since the original
// connection is not likely to be associated with a TelephonyConnection yet).
@@ -697,13 +687,11 @@ public class ImsPhoneConnection extends Connection implements
}
boolean updateParent = mParent.update(this, imsCall, state);
- boolean updateWifiState = updateWifiState();
boolean updateAddressDisplay = updateAddressDisplay(imsCall);
boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
boolean updateExtras = updateExtras(imsCall);
- return updateParent || updateWifiState || updateAddressDisplay || updateMediaCapabilities
- || updateExtras;
+ return updateParent || updateAddressDisplay || updateMediaCapabilities || updateExtras;
}
@Override
@@ -902,28 +890,6 @@ public class ImsPhoneConnection extends Connection implements
}
/**
- * Check for a change in the wifi state of the ImsPhoneCallTracker and update the
- * {@link ImsPhoneConnection} with this information.
- *
- * @return Whether the ImsPhoneCallTracker's usage of wifi has been changed.
- */
- public boolean updateWifiState() {
- // If we've received the wifi state via the ImsCallProfile.EXTRA_CALL_RAT_TYPE extra, we
- // will no longer use state updates which are based on the onFeatureCapabilityChanged
- // callback.
- if (mIsWifiStateFromExtras) {
- return false;
- }
-
- Rlog.d(LOG_TAG, "updateWifiState: " + mOwner.isVowifiEnabled());
- if (isWifi() != mOwner.isVowifiEnabled()) {
- setWifi(mOwner.isVowifiEnabled());
- return true;
- }
- return false;
- }
-
- /**
* Updates the wifi state based on the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE}.
* The call is considered to be a WIFI call if the extra value is
* {@link ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}.
@@ -934,10 +900,6 @@ public class ImsPhoneConnection extends Connection implements
if (extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE) ||
extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT)) {
- // We've received the extra indicating the radio technology, so we will continue to
- // prefer the radio technology received via this extra going forward.
- mIsWifiStateFromExtras = true;
-
ImsCall call = getImsCall();
boolean isWifi = false;
if (call != null) {
@@ -1059,6 +1021,15 @@ public class ImsPhoneConnection extends Connection implements
return sb.toString();
}
+ @Override
+ public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
+ super.setVideoProvider(videoProvider);
+
+ if (videoProvider instanceof ImsVideoCallProviderWrapper) {
+ mImsVideoCallProviderWrapper = (ImsVideoCallProviderWrapper) videoProvider;
+ }
+ }
+
/**
* Indicates whether current phone connection is emergency or not
* @return boolean: true if emergency, false otherwise
@@ -1110,4 +1081,46 @@ public class ImsPhoneConnection extends Connection implements
setVideoState(currentVideoState);
}
}
+
+ /**
+ * Issues a request to pause the video using {@link VideoProfile#STATE_PAUSED} from a source
+ * other than the InCall UI.
+ *
+ * @param source The source of the pause request.
+ */
+ public void pauseVideo(int source) {
+ if (mImsVideoCallProviderWrapper == null) {
+ return;
+ }
+
+ mImsVideoCallProviderWrapper.pauseVideo(getVideoState(), source);
+ }
+
+ /**
+ * Issues a request to resume the video using {@link VideoProfile#STATE_PAUSED} from a source
+ * other than the InCall UI.
+ *
+ * @param source The source of the resume request.
+ */
+ public void resumeVideo(int source) {
+ if (mImsVideoCallProviderWrapper == null) {
+ return;
+ }
+
+ mImsVideoCallProviderWrapper.resumeVideo(getVideoState(), source);
+ }
+
+ /**
+ * Determines if a specified source has issued a pause request.
+ *
+ * @param source The source.
+ * @return {@code true} if the source issued a pause request, {@code false} otherwise.
+ */
+ public boolean wasVideoPausedFromSource(int source) {
+ if (mImsVideoCallProviderWrapper == null) {
+ return false;
+ }
+
+ return mImsVideoCallProviderWrapper.wasVideoPausedFromSource(source);
+ }
}
diff --git a/src/java/com/android/internal/telephony/metrics/CallSessionEventBuilder.java b/src/java/com/android/internal/telephony/metrics/CallSessionEventBuilder.java
index 1cf0825f5..42d38a4b3 100644
--- a/src/java/com/android/internal/telephony/metrics/CallSessionEventBuilder.java
+++ b/src/java/com/android/internal/telephony/metrics/CallSessionEventBuilder.java
@@ -21,6 +21,7 @@ import com.android.internal.telephony.TelephonyProto.ImsConnectionState;
import com.android.internal.telephony.TelephonyProto.ImsReasonInfo;
import com.android.internal.telephony.TelephonyProto.RilDataCall;
import com.android.internal.telephony.TelephonyProto.TelephonyCallSession;
+import com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.RilCall;
import com.android.internal.telephony.TelephonyProto.TelephonyServiceState;
import com.android.internal.telephony.TelephonyProto.TelephonySettings;
@@ -124,4 +125,9 @@ public class CallSessionEventBuilder {
mEvent.setNitzTimestampMillis(timestamp);
return this;
}
+
+ public CallSessionEventBuilder setRilCalls(RilCall[] rilCalls) {
+ mEvent.calls = rilCalls;
+ return this;
+ }
}
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
index 92e3f0af7..eddb1c0c4 100644
--- a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
@@ -21,11 +21,14 @@ import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.TelephonyHistogram;
import android.util.Base64;
+import android.util.Log;
import android.util.SparseArray;
import com.android.ims.ImsConfig;
import com.android.ims.ImsReasonInfo;
import com.android.ims.internal.ImsCallSession;
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.GsmCdmaConnection;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RIL;
import com.android.internal.telephony.RILConstants;
@@ -36,6 +39,9 @@ import com.android.internal.telephony.TelephonyProto.ImsConnectionState;
import com.android.internal.telephony.TelephonyProto.RilDataCall;
import com.android.internal.telephony.TelephonyProto.SmsSession;
import com.android.internal.telephony.TelephonyProto.TelephonyCallSession;
+import com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.RilCall;
+import com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.RilCall.Type.*;
+import com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.CallState.*;
import com.android.internal.telephony.TelephonyProto.TelephonyEvent;
import com.android.internal.telephony.TelephonyProto.TelephonyEvent.RilDeactivateDataCall;
import com.android.internal.telephony.TelephonyProto.TelephonyEvent.RilSetupDataCall;
@@ -58,6 +64,7 @@ import java.util.Deque;
import java.util.List;
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;
@@ -1012,22 +1019,106 @@ public class TelephonyMetrics {
}
/**
+ * Write CS call list event
+ *
+ * @param phoneId Phone id
+ * @param connections Array of GsmCdmaConnection objects
+ */
+ public void writeRilCallList(int phoneId, ArrayList<GsmCdmaConnection> connections) {
+ if (VDBG) {
+ Rlog.v(TAG, "Logging CallList Changed Connections Size = " + connections.size());
+ }
+ InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId);
+ if (callSession == null) {
+ Rlog.e(TAG, "writeRilCallList: Call session is missing");
+ } else {
+ RilCall[] calls = convertConnectionsToRilCalls(connections);
+ callSession.addEvent(
+ new CallSessionEventBuilder(
+ TelephonyCallSession.Event.Type.RIL_CALL_LIST_CHANGED)
+ .setRilCalls(calls)
+ );
+ if (VDBG) Rlog.v(TAG, "Logged Call list changed");
+ }
+ }
+
+ private RilCall[] convertConnectionsToRilCalls(ArrayList<GsmCdmaConnection> mConnections) {
+ RilCall[] calls = new RilCall[mConnections.size()];
+ for (int i = 0; i < mConnections.size(); i++) {
+ calls[i] = new RilCall();
+ calls[i].setIndex(i);
+ convertConnectionToRilCall(mConnections.get(i), calls[i]);
+ }
+ return calls;
+ }
+
+ private void convertConnectionToRilCall(GsmCdmaConnection conn, RilCall call) {
+ if (conn.isIncoming()) {
+ call.setType(TelephonyCallSession.Event.RilCall.Type.MT);
+ } else {
+ call.setType(TelephonyCallSession.Event.RilCall.Type.MO);
+ }
+ switch (conn.getState()) {
+ case IDLE:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_IDLE);
+ break;
+ case ACTIVE:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_ACTIVE);
+ break;
+ case HOLDING:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_HOLDING);
+ break;
+ case DIALING:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_DIALING);
+ break;
+ case ALERTING:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_ALERTING);
+ break;
+ case INCOMING:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_INCOMING);
+ break;
+ case WAITING:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_WAITING);
+ break;
+ case DISCONNECTED:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_DISCONNECTED);
+ break;
+ case DISCONNECTING:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_DISCONNECTING);
+ break;
+ default:
+ call.setState(TelephonyCallSession.Event.CallState.CALL_UNKNOWN);
+ break;
+ }
+ call.setCallEndReason(conn.getDisconnectCause());
+ call.setIsMultiparty(conn.isMultiparty());
+ }
+
+ /**
* Write dial event
*
* @param phoneId Phone id
- * @param rilSerial RIL request serial number
+ * @param conn Connection object created to track this call
* @param clirMode CLIR (Calling Line Identification Restriction) mode
* @param uusInfo User-to-User signaling Info
*/
- public void writeRilDial(int phoneId, int rilSerial, int clirMode, UUSInfo uusInfo) {
+ public void writeRilDial(int phoneId, GsmCdmaConnection conn, int clirMode, UUSInfo uusInfo) {
InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId);
-
- callSession.addEvent(callSession.startElapsedTimeMs,
- new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST)
- .setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_DIAL)
- .setRilRequestId(rilSerial)
- );
+ if (VDBG) Rlog.v(TAG, "Logging Dial Connection = " + conn);
+ if (callSession == null) {
+ Rlog.e(TAG, "writeRilDial: Call session is missing");
+ } else {
+ RilCall[] calls = new RilCall[1];
+ calls[0] = new RilCall();
+ calls[0].setIndex(-1);
+ convertConnectionToRilCall(conn, calls[0]);
+ callSession.addEvent(callSession.startElapsedTimeMs,
+ new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST)
+ .setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_DIAL)
+ .setRilCalls(calls));
+ if (VDBG) Rlog.v(TAG, "Logged Dial event");
+ }
}
/**
@@ -1047,19 +1138,23 @@ public class TelephonyMetrics {
* Write call hangup event
*
* @param phoneId Phone id
- * @param rilSerial RIL request serial number
+ * @param conn Connection object associated with the call that is being hung-up
* @param callId Call id
*/
- public void writeRilHangup(int phoneId, int rilSerial, int callId) {
+ public void writeRilHangup(int phoneId, GsmCdmaConnection conn, int callId) {
InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
if (callSession == null) {
- Rlog.e(TAG, "Call session is missing");
+ Rlog.e(TAG, "writeRilHangup: Call session is missing");
} else {
+ RilCall[] calls = new RilCall[1];
+ calls[0] = new RilCall();
+ calls[0].setIndex(callId);
+ convertConnectionToRilCall(conn, calls[0]);
callSession.addEvent(
new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST)
.setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_HANGUP)
- .setRilRequestId(rilSerial)
- .setCallIndex(callId));
+ .setRilCalls(calls));
+ if (VDBG) Rlog.v(TAG, "Logged Hangup event");
}
}
@@ -1072,7 +1167,7 @@ public class TelephonyMetrics {
public void writeRilAnswer(int phoneId, int rilSerial) {
InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
if (callSession == null) {
- Rlog.e(TAG, "Call session is missing");
+ Rlog.e(TAG, "writeRilAnswer: Call session is missing");
} else {
callSession.addEvent(
new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST)
@@ -1090,7 +1185,7 @@ public class TelephonyMetrics {
public void writeRilSrvcc(int phoneId, int rilSrvccState) {
InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
if (callSession == null) {
- Rlog.e(TAG, "Call session is missing");
+ Rlog.e(TAG, "writeRilSrvcc: Call session is missing");
} else {
callSession.addEvent(
new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_CALL_SRVCC)
@@ -1180,7 +1275,7 @@ public class TelephonyMetrics {
int rilRequest) {
InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
if (callSession == null) {
- Rlog.e(TAG, "Call session is missing");
+ Rlog.e(TAG, "writeOnCallSolicitedResponse: Call session is missing");
} else {
callSession.addEvent(new CallSessionEventBuilder(
TelephonyCallSession.Event.Type.RIL_RESPONSE)
@@ -1295,7 +1390,7 @@ public class TelephonyMetrics {
InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
if (callSession == null) {
- Rlog.e(TAG, "Call session is missing");
+ Rlog.e(TAG, "writePhoneState: Call session is missing");
} else {
if (state == TelephonyCallSession.Event.PhoneState.STATE_IDLE) {
finishCallSession(callSession);
diff --git a/src/java/com/android/internal/telephony/uicc/IccConstants.java b/src/java/com/android/internal/telephony/uicc/IccConstants.java
index 5ed699ec9..01c3570dc 100644
--- a/src/java/com/android/internal/telephony/uicc/IccConstants.java
+++ b/src/java/com/android/internal/telephony/uicc/IccConstants.java
@@ -30,21 +30,21 @@ public interface IccConstants {
static final int EF_EXT2 = 0x6F4B;
static final int EF_EXT3 = 0x6F4C;
static final int EF_EXT5 = 0x6F4E;
- static final int EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN]
+ static final int EF_EXT6 = 0x6FC8; // Ext record for EF[MBDN]
static final int EF_MWIS = 0x6FCA;
- static final int EF_MBDN = 0x6fc7;
- static final int EF_PNN = 0x6fc5;
- static final int EF_OPL = 0x6fc6;
+ static final int EF_MBDN = 0x6FC7;
+ static final int EF_PNN = 0x6FC5;
+ static final int EF_OPL = 0x6FC6;
static final int EF_SPN = 0x6F46;
static final int EF_SMS = 0x6F3C;
- static final int EF_ICCID = 0x2fe2;
+ static final int EF_ICCID = 0x2FE2;
static final int EF_AD = 0x6FAD;
- static final int EF_MBI = 0x6fc9;
- static final int EF_MSISDN = 0x6f40;
- static final int EF_SPDI = 0x6fcd;
- static final int EF_SST = 0x6f38;
+ static final int EF_MBI = 0x6FC9;
+ static final int EF_MSISDN = 0x6F40;
+ static final int EF_SPDI = 0x6FCD;
+ static final int EF_SST = 0x6F38;
static final int EF_CFIS = 0x6FCB;
- static final int EF_IMG = 0x4f20;
+ static final int EF_IMG = 0x4F20;
// USIM SIM file ids from TS 131.102
public static final int EF_PBR = 0x4F30;
@@ -54,13 +54,13 @@ public interface IccConstants {
static final int EF_MAILBOX_CPHS = 0x6F17;
static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
static final int EF_CFF_CPHS = 0x6F13;
- static final int EF_SPN_CPHS = 0x6f14;
- static final int EF_SPN_SHORT_CPHS = 0x6f18;
- static final int EF_INFO_CPHS = 0x6f16;
- static final int EF_CSP_CPHS = 0x6f15;
+ static final int EF_SPN_CPHS = 0x6F14;
+ static final int EF_SPN_SHORT_CPHS = 0x6F18;
+ static final int EF_INFO_CPHS = 0x6F16;
+ static final int EF_CSP_CPHS = 0x6F15;
// CDMA RUIM file ids from 3GPP2 C.S0023-0
- static final int EF_CST = 0x6f32;
+ static final int EF_CST = 0x6F32;
static final int EF_RUIM_SPN =0x6F41;
// ETSI TS.102.221
@@ -79,12 +79,27 @@ public interface IccConstants {
static final int EF_CSIM_MIPUPP = 0x6F4D;
//ISIM access
- static final int EF_IMPU = 0x6f04;
- static final int EF_IMPI = 0x6f02;
- static final int EF_DOMAIN = 0x6f03;
- static final int EF_IST = 0x6f07;
- static final int EF_PCSCF = 0x6f09;
- static final int EF_PSI = 0x6fe5;
+ static final int EF_IMPU = 0x6F04;
+ static final int EF_IMPI = 0x6F02;
+ static final int EF_DOMAIN = 0x6F03;
+ static final int EF_IST = 0x6F07;
+ static final int EF_PCSCF = 0x6F09;
+ static final int EF_PSI = 0x6FE5;
+
+ //PLMN Selection Information w/ Access Technology TS 131.102
+ static final int EF_PLMN_W_ACT = 0x6F60;
+ static final int EF_OPLMN_W_ACT = 0x6F61;
+ static final int EF_HPLMN_W_ACT = 0x6F62;
+
+ //Equivalent Home and Forbidden PLMN Lists TS 131.102
+ static final int EF_EHPLMN = 0x6FD9;
+ static final int EF_FPLMN = 0x6F7B;
+
+ // Last Roaming Selection Indicator
+ static final int EF_LRPLMNSI = 0x6FDC;
+
+ //Search interval for higher priority PLMNs
+ static final int EF_HPPLMN = 0x6F31;
//plmnwact
static final int EF_PLMNWACT = 0x6F60;
diff --git a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
index 54e05f7ca..6f944bda1 100644
--- a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.uicc;
import android.os.*;
+
import com.android.internal.telephony.CommandsInterface;
import java.util.ArrayList;
@@ -25,6 +26,7 @@ import java.util.ArrayList;
* {@hide}
*/
public abstract class IccFileHandler extends Handler implements IccConstants {
+ private static final boolean VDBG = false;
//from TS 11.11 9.1 or elsewhere
static protected final int COMMAND_READ_BINARY = 0xb0;
@@ -550,6 +552,11 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
size = tlvData.mFileSize;
} else {
+ if (VDBG) {
+ logd(String.format("Contents of the Select Response for command %x: ", fileid)
+ + IccUtils.bytesToHexString(data));
+ }
+
if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
throw new IccFileTypeMismatch();
}
@@ -663,7 +670,6 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
protected abstract String getEFPath(int efid);
protected abstract void logd(String s);
-
protected abstract void loge(String s);
}
diff --git a/src/java/com/android/internal/telephony/uicc/IccIoResult.java b/src/java/com/android/internal/telephony/uicc/IccIoResult.java
index 6f0b5c3fd..4a35e1460 100644
--- a/src/java/com/android/internal/telephony/uicc/IccIoResult.java
+++ b/src/java/com/android/internal/telephony/uicc/IccIoResult.java
@@ -22,6 +22,147 @@ package com.android.internal.telephony.uicc;
*/
public class
IccIoResult {
+
+ private static final String UNKNOWN_ERROR = "unknown";
+
+ private String getErrorString() {
+ // Errors from 3gpp 11.11 9.4.1
+ // Additional Errors from ETSI 102.221
+ //
+ // All error codes below are copied directly from their respective specification
+ // without modification except in cases where necessary string formatting has been omitted.
+ switch(sw1) {
+ case 0x62:
+ switch(sw2) {
+ case 0x00: return "No information given,"
+ + " state of non volatile memory unchanged";
+ case 0x81: return "Part of returned data may be corrupted";
+ case 0x82: return "End of file/record reached before reading Le bytes";
+ case 0x83: return "Selected file invalidated";
+ case 0x84: return "Selected file in termination state";
+ case 0xF1: return "More data available";
+ case 0xF2: return "More data available and proactive command pending";
+ case 0xF3: return "Response data available";
+ }
+ break;
+ case 0x63:
+ if (sw2 >> 4 == 0x0C) {
+ return "Command successful but after using an internal"
+ + "update retry routine but Verification failed";
+ }
+ switch(sw2) {
+ case 0xF1: return "More data expected";
+ case 0xF2: return "More data expected and proactive command pending";
+ }
+ break;
+ case 0x64:
+ switch(sw2) {
+ case 0x00: return "No information given,"
+ + " state of non-volatile memory unchanged";
+ }
+ break;
+ case 0x65:
+ switch(sw2) {
+ case 0x00: return "No information given, state of non-volatile memory changed";
+ case 0x81: return "Memory problem";
+ }
+ break;
+ case 0x67:
+ switch(sw2) {
+ case 0x00: return "incorrect parameter P3";
+ default: return "The interpretation of this status word is command dependent";
+ }
+ // break;
+ case 0x6B: return "incorrect parameter P1 or P2";
+ case 0x6D: return "unknown instruction code given in the command";
+ case 0x6E: return "wrong instruction class given in the command";
+ case 0x6F:
+ switch(sw2) {
+ case 0x00: return "technical problem with no diagnostic given";
+ default: return "The interpretation of this status word is command dependent";
+ }
+ // break;
+ case 0x68:
+ switch(sw2) {
+ case 0x00: return "No information given";
+ case 0x81: return "Logical channel not supported";
+ case 0x82: return "Secure messaging not supported";
+ }
+ break;
+ case 0x69:
+ switch(sw2) {
+ case 0x00: return "No information given";
+ case 0x81: return "Command incompatible with file structure";
+ case 0x82: return "Security status not satisfied";
+ case 0x83: return "Authentication/PIN method blocked";
+ case 0x84: return "Referenced data invalidated";
+ case 0x85: return "Conditions of use not satisfied";
+ case 0x86: return "Command not allowed (no EF selected)";
+ case 0x89: return "Command not allowed - secure channel -"
+ + " security not satisfied";
+ }
+ break;
+ case 0x6A:
+ switch(sw2) {
+ case 0x80: return "Incorrect parameters in the data field";
+ case 0x81: return "Function not supported";
+ case 0x82: return "File not found";
+ case 0x83: return "Record not found";
+ case 0x84: return "Not enough memory space";
+ case 0x86: return "Incorrect parameters P1 to P2";
+ case 0x87: return "Lc inconsistent with P1 to P2";
+ case 0x88: return "Referenced data not found";
+ }
+ break;
+ case 0x90: return null; // success
+ case 0x91: return null; // success
+ //Status Code 0x92 has contradictory meanings from 11.11 and 102.221 10.2.1.1
+ case 0x92:
+ if (sw2 >> 4 == 0) {
+ return "command successful but after using an internal update retry routine";
+ }
+ switch(sw2) {
+ case 0x40: return "memory problem";
+ }
+ break;
+ case 0x93:
+ switch(sw2) {
+ case 0x00:
+ return "SIM Application Toolkit is busy. Command cannot be executed"
+ + " at present, further normal commands are allowed.";
+ }
+ break;
+ case 0x94:
+ switch(sw2) {
+ case 0x00: return "no EF selected";
+ case 0x02: return "out f range (invalid address)";
+ case 0x04: return "file ID not found/pattern not found";
+ case 0x08: return "file is inconsistent with the command";
+ }
+ break;
+ case 0x98:
+ switch(sw2) {
+ case 0x02: return "no CHV initialized";
+ case 0x04: return "access condition not fulfilled/"
+ + "unsuccessful CHV verification, at least one attempt left/"
+ + "unsuccessful UNBLOCK CHV verification, at least one attempt left/"
+ + "authentication failed";
+ case 0x08: return "in contradiction with CHV status";
+ case 0x10: return "in contradiction with invalidation status";
+ case 0x40: return "unsuccessful CHV verification, no attempt left/"
+ + "unsuccessful UNBLOCK CHV verification, no attempt left/"
+ + "CHV blocked"
+ + "UNBLOCK CHV blocked";
+ case 0x50: return "increase cannot be performed, Max value reached";
+ }
+ break;
+ case 0x9E: return null; // success
+ case 0x9F: return null; // success
+ }
+ return UNKNOWN_ERROR;
+ }
+
+
public int sw1;
public int sw2;
@@ -39,8 +180,8 @@ IccIoResult {
@Override
public String toString() {
- return "IccIoResponse sw1:0x" + Integer.toHexString(sw1) + " sw2:0x"
- + Integer.toHexString(sw2);
+ return "IccIoResult sw1:0x" + Integer.toHexString(sw1) + " sw2:0x"
+ + Integer.toHexString(sw2) + ((!success()) ? " Error: " + getErrorString() : "");
}
/**
diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index 41dbe46e2..b180010ac 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -22,6 +22,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.Registrant;
import android.os.RegistrantList;
+
import android.telephony.Rlog;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
@@ -90,6 +91,13 @@ public abstract class IccRecords extends Handler implements IccConstants {
protected String mGid2;
protected String mPrefLang;
+ protected PlmnActRecord[] mHplmnActRecords;
+ protected PlmnActRecord[] mOplmnActRecords;
+ protected PlmnActRecord[] mPlmnActRecords;
+
+ protected String[] mEhplmns;
+ protected String[] mFplmns;
+
private final Object mLock = new Object();
// ***** Constants
@@ -103,7 +111,6 @@ public abstract class IccRecords extends Handler implements IccConstants {
public static final int SPN_RULE_SHOW_PLMN = 0x02;
// ***** Event Constants
- protected static final int EVENT_SET_MSISDN_DONE = 30;
public static final int EVENT_MWI = 0; // Message Waiting indication
public static final int EVENT_CFI = 1; // Call Forwarding indication
public static final int EVENT_SPN = 2; // Service Provider Name
@@ -332,34 +339,13 @@ public abstract class IccRecords extends Handler implements IccConstants {
return null;
}
- /**
- * Set subscriber number to SIM record
- *
- * The subscriber number is stored in EF_MSISDN (TS 51.011)
- *
- * When the operation is complete, onComplete will be sent to its handler
- *
- * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters)
- * @param number dailing nubmer (up to 20 digits)
- * if the number starts with '+', then set to international TOA
- * @param onComplete
- * onComplete.obj will be an AsyncResult
- * ((AsyncResult)onComplete.obj).exception == null on success
- * ((AsyncResult)onComplete.obj).exception != null on fail
- */
public void setMsisdnNumber(String alphaTag, String number,
Message onComplete) {
-
- mMsisdn = number;
- mMsisdnTag = alphaTag;
-
- if (DBG) log("Set MSISDN: " + mMsisdnTag +" " + mMsisdn);
-
-
- AdnRecord adn = new AdnRecord(mMsisdnTag, mMsisdn);
-
- new AdnRecordLoader(mFh).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null,
- obtainMessage(EVENT_SET_MSISDN_DONE, onComplete));
+ loge("setMsisdn() should not be invoked on base IccRecords");
+ // synthesize a "File Not Found" exception and return it
+ AsyncResult.forMessage(onComplete).exception =
+ (new IccIoResult(0x6A, 0x82, (byte[]) null)).getException();
+ onComplete.sendToTarget();
}
public String getMsisdnAlphaTag() {
diff --git a/src/java/com/android/internal/telephony/uicc/IccUtils.java b/src/java/com/android/internal/telephony/uicc/IccUtils.java
index fdcc12537..67de87f2b 100644
--- a/src/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/src/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -23,6 +23,7 @@ import android.graphics.Color;
import android.telephony.Rlog;
import com.android.internal.telephony.GsmAlphabet;
+
import java.io.UnsupportedEncodingException;
/**
@@ -61,6 +62,28 @@ public class IccUtils {
}
/**
+ * PLMN (MCC/MNC) is encoded as per 24.008 10.5.1.3
+ * Returns a concatenated string of MCC+MNC, stripping
+ * a trailing character for a 2-digit MNC
+ */
+ public static String bcdPlmnToString(byte[] data, int offset) {
+ if (offset + 3 > data.length) {
+ return null;
+ }
+ byte[] trans = new byte[3];
+ trans[0] = (byte) ((data[0 + offset] << 4) | ((data[0 + offset] >> 4) & 0xF));
+ trans[1] = (byte) ((data[1 + offset] << 4) | (data[2 + offset] & 0xF));
+ trans[2] = (byte) ((data[2 + offset] & 0xF0) | ((data[1 + offset] >> 4) & 0xF));
+ String ret = bytesToHexString(trans);
+
+ // For a 2-digit MNC we trim the trailing 'f'
+ if (ret.endsWith("f")) {
+ ret = ret.substring(0, ret.length() - 1);
+ }
+ return ret;
+ }
+
+ /**
* Some fields (like ICC ID) in GSM SIMs are stored as nibble-swizzled BCH
*/
public static String
diff --git a/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java b/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java
new file mode 100644
index 000000000..a4cf7cc1c
--- /dev/null
+++ b/src/java/com/android/internal/telephony/uicc/PlmnActRecord.java
@@ -0,0 +1,144 @@
+/*
+ * 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.uicc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Rlog;
+
+import java.util.Arrays;
+
+/**
+ * {@hide}
+ */
+public class PlmnActRecord implements Parcelable {
+ private static final String LOG_TAG = "PlmnActRecord";
+
+ // Values specified in 3GPP 31.102 sec. 4.2.5
+ public static final int ACCESS_TECH_UTRAN = 0x8000;
+ public static final int ACCESS_TECH_EUTRAN = 0x4000;
+ public static final int ACCESS_TECH_GSM = 0x0080;
+ public static final int ACCESS_TECH_GSM_COMPACT = 0x0040;
+ public static final int ACCESS_TECH_CDMA2000_HRPD = 0x0020;
+ public static final int ACCESS_TECH_CDMA2000_1XRTT = 0x0010;
+ public static final int ACCESS_TECH_RESERVED = 0x3F0F;
+
+ public static final int ENCODED_LENGTH = 5;
+
+ public final String plmn;
+ public final int accessTechs;
+
+ private static final boolean VDBG = true;
+
+ public static final Parcelable.Creator<PlmnActRecord> CREATOR =
+ new Parcelable.Creator<PlmnActRecord>() {
+ @Override
+ public PlmnActRecord createFromParcel(Parcel source) {
+ return new PlmnActRecord(source.readString(), source.readInt());
+ }
+
+ @Override
+ public PlmnActRecord[] newArray(int size) {
+ return new PlmnActRecord[size];
+ }
+ };
+
+ /* From 3gpp 31.102 section 4.2.5
+ * Bytes 0-2 bcd-encoded PLMN-ID
+ * Bytes 3-4 bitfield of access technologies
+ */
+ public PlmnActRecord(byte[] bytes, int offset) {
+ if (VDBG) Rlog.v(LOG_TAG, "Creating PlmnActRecord " + offset);
+ this.plmn = IccUtils.bcdPlmnToString(bytes, offset);
+ this.accessTechs = ((int) bytes[offset + 3] << 8) | bytes[offset + 4];
+ }
+
+ private PlmnActRecord(String plmn, int accessTechs) {
+ this.plmn = plmn;
+ this.accessTechs = accessTechs;
+ }
+
+ private String accessTechString() {
+ if (accessTechs == 0) {
+ return "NONE";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ if ((accessTechs & ACCESS_TECH_UTRAN) != 0) {
+ sb.append("UTRAN|");
+ }
+ if ((accessTechs & ACCESS_TECH_EUTRAN) != 0) {
+ sb.append("EUTRAN|");
+ }
+ if ((accessTechs & ACCESS_TECH_GSM) != 0) {
+ sb.append("GSM|");
+ }
+ if ((accessTechs & ACCESS_TECH_GSM_COMPACT) != 0) {
+ sb.append("GSM_COMPACT|");
+ }
+ if ((accessTechs & ACCESS_TECH_CDMA2000_HRPD) != 0) {
+ sb.append("CDMA2000_HRPD|");
+ }
+ if ((accessTechs & ACCESS_TECH_CDMA2000_1XRTT) != 0) {
+ sb.append("CDMA2000_1XRTT|");
+ }
+ if ((accessTechs & ACCESS_TECH_RESERVED) != 0) {
+ sb.append(String.format("UNKNOWN:%x|", accessTechs & ACCESS_TECH_RESERVED));
+ }
+ // Trim the tailing pipe character
+ return sb.substring(0, sb.length() - 1);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{PLMN=%s,AccessTechs=%s}", plmn, accessTechString());
+ }
+
+ /**
+ * Convenience method for extracting all records from encoded bytes
+ */
+ public static PlmnActRecord[] getRecords(byte[] recordBytes) {
+ if (recordBytes == null || recordBytes.length == 0
+ || recordBytes.length % ENCODED_LENGTH != 0) {
+ Rlog.e(LOG_TAG, "Malformed PlmnActRecord, bytes: "
+ + ((recordBytes != null) ? Arrays.toString(recordBytes) : null));
+ return null;
+ }
+ int numRecords = recordBytes.length / ENCODED_LENGTH;
+ if (VDBG) Rlog.v(LOG_TAG, "Extracting Logs, count=" + numRecords);
+
+ PlmnActRecord[] records = new PlmnActRecord[numRecords];
+
+ for(int i = 0; i < numRecords; i++) {
+ records[i] = new PlmnActRecord(recordBytes, i * ENCODED_LENGTH);
+ }
+ return records;
+ }
+
+ // Parcelable Implementation
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(plmn);
+ dest.writeInt(accessTechs);
+ }
+
+}
diff --git a/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java b/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
index 4d782a31f..2bcf04275 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMFileHandler.java
@@ -56,8 +56,6 @@ public final class SIMFileHandler extends IccFileHandler implements IccConstants
case EF_CFIS:
case EF_GID1:
case EF_GID2:
- return MF_SIM + DF_GSM;
-
case EF_MAILBOX_CPHS:
case EF_VOICE_MAIL_INDICATOR_CPHS:
case EF_CFF_CPHS:
diff --git a/src/java/com/android/internal/telephony/uicc/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
index f50d5d392..ccae4b33a 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
@@ -20,10 +20,12 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Message;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionInfo;
import android.text.TextUtils;
@@ -52,6 +54,8 @@ public class SIMRecords extends IccRecords {
private static final boolean CRASH_RIL = false;
+ private static final boolean VDBG = false;
+
// ***** Instance Variables
VoiceMailConstants mVmConfig;
@@ -139,35 +143,46 @@ public class SIMRecords extends IccRecords {
private static final int CFIS_ADN_EXTENSION_ID_OFFSET = 15;
// ***** Event Constants
- private static final int EVENT_GET_IMSI_DONE = 3;
- private static final int EVENT_GET_ICCID_DONE = 4;
- private static final int EVENT_GET_MBI_DONE = 5;
- private static final int EVENT_GET_MBDN_DONE = 6;
- private static final int EVENT_GET_MWIS_DONE = 7;
- private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8;
- protected static final int EVENT_GET_AD_DONE = 9; // Admin data on SIM
- protected static final int EVENT_GET_MSISDN_DONE = 10;
- private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11;
- private static final int EVENT_GET_SPN_DONE = 12;
- private static final int EVENT_GET_SPDI_DONE = 13;
- private static final int EVENT_UPDATE_DONE = 14;
- private static final int EVENT_GET_PNN_DONE = 15;
- protected static final int EVENT_GET_SST_DONE = 17;
- private static final int EVENT_GET_ALL_SMS_DONE = 18;
- private static final int EVENT_MARK_SMS_READ_DONE = 19;
- private static final int EVENT_SET_MBDN_DONE = 20;
- private static final int EVENT_SMS_ON_SIM = 21;
- private static final int EVENT_GET_SMS_DONE = 22;
- private static final int EVENT_GET_CFF_DONE = 24;
- private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25;
- private static final int EVENT_GET_INFO_CPHS_DONE = 26;
- // private static final int EVENT_SET_MSISDN_DONE = 30; Defined in IccRecords as 30
- private static final int EVENT_GET_CFIS_DONE = 32;
- private static final int EVENT_GET_CSP_CPHS_DONE = 33;
- private static final int EVENT_GET_GID1_DONE = 34;
- private static final int EVENT_APP_LOCKED = 35;
- private static final int EVENT_GET_GID2_DONE = 36;
- private static final int EVENT_CARRIER_CONFIG_CHANGED = 37;
+ private static final int SIM_RECORD_EVENT_BASE = 0x00;
+ private static final int EVENT_GET_IMSI_DONE = 3 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_ICCID_DONE = 4 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_MBI_DONE = 5 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_MBDN_DONE = 6 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_MWIS_DONE = 7 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE = 8 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_AD_DONE = 9 + SIM_RECORD_EVENT_BASE; // Admin data on SIM
+ private static final int EVENT_GET_MSISDN_DONE = 10 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CPHS_MAILBOX_DONE = 11 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SPN_DONE = 12 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SPDI_DONE = 13 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_UPDATE_DONE = 14 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_PNN_DONE = 15 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SST_DONE = 17 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_ALL_SMS_DONE = 18 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_MARK_SMS_READ_DONE = 19 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SET_MBDN_DONE = 20 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SMS_ON_SIM = 21 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_SMS_DONE = 22 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CFF_DONE = 24 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SET_CPHS_MAILBOX_DONE = 25 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_INFO_CPHS_DONE = 26 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_SET_MSISDN_DONE = 30 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CFIS_DONE = 32 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_CSP_CPHS_DONE = 33 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_GID1_DONE = 34 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_GID2_DONE = 36 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_PLMN_W_ACT_DONE = 37 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_OPLMN_W_ACT_DONE = 38 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_HPLMN_W_ACT_DONE = 39 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_EHPLMN_DONE = 40 + SIM_RECORD_EVENT_BASE;
+ private static final int EVENT_GET_FPLMN_DONE = 41 + SIM_RECORD_EVENT_BASE;
+
+ // TODO: Possibly move these to IccRecords.java
+ private static final int SYSTEM_EVENT_BASE = 0x100;
+ private static final int EVENT_CARRIER_CONFIG_CHANGED = 1 + SYSTEM_EVENT_BASE;
+ private static final int EVENT_APP_LOCKED = 2 + SYSTEM_EVENT_BASE;
+ private static final int EVENT_SIM_REFRESH = 3 + SYSTEM_EVENT_BASE;
+
// Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
@@ -260,6 +275,11 @@ public class SIMRecords extends IccRecords {
mPnnHomeName = null;
mGid1 = null;
mGid2 = null;
+ mPlmnActRecords = null;
+ mOplmnActRecords = null;
+ mHplmnActRecords = null;
+ mFplmns = null;
+ mEhplmns = null;
mAdnCache.reset();
@@ -1230,6 +1250,72 @@ public class SIMRecords extends IccRecords {
break;
+ case EVENT_GET_PLMN_W_ACT_DONE:
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+
+ if (ar.exception != null || data == null) {
+ loge("Failed getting User PLMN with Access Tech Records: " + ar.exception);
+ break;
+ } else {
+ log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
+ mPlmnActRecords = PlmnActRecord.getRecords(data);
+ if (VDBG) log("PlmnActRecords=" + Arrays.toString(mPlmnActRecords));
+ }
+ break;
+
+ case EVENT_GET_OPLMN_W_ACT_DONE:
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Operator PLMN with Access Tech Records: "
+ + ar.exception);
+ break;
+ } else {
+ log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
+ mOplmnActRecords = PlmnActRecord.getRecords(data);
+ if (VDBG) log("OplmnActRecord[]=" + Arrays.toString(mOplmnActRecords));
+ }
+ break;
+
+ case EVENT_GET_HPLMN_W_ACT_DONE:
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Home PLMN with Access Tech Records: " + ar.exception);
+ break;
+ } else {
+ log("Received a PlmnActRecord, raw=" + IccUtils.bytesToHexString(data));
+ mHplmnActRecords = PlmnActRecord.getRecords(data);
+ log("HplmnActRecord[]=" + Arrays.toString(mHplmnActRecords));
+ }
+ break;
+
+ case EVENT_GET_EHPLMN_DONE:
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Equivalent Home PLMNs: " + ar.exception);
+ break;
+ } else {
+ mEhplmns = parseBcdPlmnList(data, "Equivalent Home");
+ }
+ break;
+
+ case EVENT_GET_FPLMN_DONE:
+ isRecordLoadResponse = true;
+ ar = (AsyncResult) msg.obj;
+ data = (byte[]) ar.result;
+ if (ar.exception != null || data == null) {
+ loge("Failed getting Forbidden PLMNs: " + ar.exception);
+ break;
+ } else {
+ mFplmns = parseBcdPlmnList(data, "Forbidden");
+ }
+ break;
+
case EVENT_CARRIER_CONFIG_CHANGED:
handleCarrierNameOverride();
break;
@@ -1620,6 +1706,17 @@ public class SIMRecords extends IccRecords {
mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE));
mRecordsToLoad++;
+ mFh.loadEFTransparent(EF_PLMN_W_ACT, obtainMessage(EVENT_GET_PLMN_W_ACT_DONE));
+
+ mFh.loadEFTransparent(EF_OPLMN_W_ACT, obtainMessage(EVENT_GET_OPLMN_W_ACT_DONE));
+
+ mFh.loadEFTransparent(EF_HPLMN_W_ACT, obtainMessage(EVENT_GET_HPLMN_W_ACT_DONE));
+
+ mFh.loadEFTransparent(EF_EHPLMN, obtainMessage(EVENT_GET_EHPLMN_DONE));
+
+ mFh.loadEFTransparent(EF_FPLMN, obtainMessage(EVENT_GET_FPLMN_DONE));
+ mRecordsToLoad++;
+
loadEfLiAndEfPl();
mFh.getEFLinearRecordSize(EF_SMS, obtainMessage(EVENT_GET_SMS_RECORD_SIZE_DONE));
@@ -1913,6 +2010,25 @@ public class SIMRecords extends IccRecords {
}
/**
+ * convert a byte array of packed plmns to an array of strings
+ */
+ private String[] parseBcdPlmnList(byte[] data, String description) {
+ final int packedBcdPlmnLenBytes = 3;
+ log("Received " + description + " PLMNs, raw=" + IccUtils.bytesToHexString(data));
+ if (data.length == 0 || (data.length % packedBcdPlmnLenBytes) != 0) {
+ loge("Received invalid " + description + " PLMN list");
+ return null;
+ }
+ int numPlmns = data.length / packedBcdPlmnLenBytes;
+ String[] ret = new String[numPlmns];
+ for (int i = 0; i < numPlmns; i++) {
+ ret[i] = IccUtils.bcdPlmnToString(data, i * packedBcdPlmnLenBytes);
+ }
+ if (VDBG) logv(description + " PLMNs: " + Arrays.toString(ret));
+ return ret;
+ }
+
+ /**
* check to see if Mailbox Number is allocated and activated in CPHS SST
*/
private boolean isCphsMailboxEnabled() {
@@ -2009,6 +2125,11 @@ public class SIMRecords extends IccRecords {
pw.println(" mUsimServiceTable=" + mUsimServiceTable);
pw.println(" mGid1=" + mGid1);
pw.println(" mGid2=" + mGid2);
+ pw.println(" mPlmnActRecords[]=" + Arrays.toString(mPlmnActRecords));
+ pw.println(" mOplmnActRecords[]=" + Arrays.toString(mOplmnActRecords));
+ pw.println(" mHplmnActRecords[]=" + Arrays.toString(mHplmnActRecords));
+ pw.println(" mFplmns[]=" + Arrays.toString(mFplmns));
+ pw.println(" mEhplmns[]=" + Arrays.toString(mEhplmns));
pw.flush();
}
}
diff --git a/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java b/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
index 97d9d4083..f2834f7ec 100644
--- a/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/UsimFileHandler.java
@@ -61,8 +61,13 @@ public final class UsimFileHandler extends IccFileHandler implements IccConstant
case EF_GID1:
case EF_GID2:
case EF_LI:
- case EF_PLMNWACT:
- case EF_HPLMNWACT:
+ case EF_PLMN_W_ACT:
+ case EF_OPLMN_W_ACT:
+ case EF_HPLMN_W_ACT:
+ case EF_EHPLMN:
+ case EF_FPLMN:
+ case EF_LRPLMNSI:
+ case EF_HPPLMN:
return MF_SIM + DF_ADF;
case EF_PBR:
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FakeSmsContentProvider.java b/tests/telephonytests/src/com/android/internal/telephony/FakeSmsContentProvider.java
index 1806c3cb1..17c18ecd6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeSmsContentProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeSmsContentProvider.java
@@ -62,7 +62,8 @@ public class FakeSmsContentProvider extends MockContentProvider {
SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
"pdu TEXT," + // the raw PDU for this part
"deleted INTEGER DEFAULT 0," + // bool to indicate if row is deleted
- "message_body TEXT);"); // message body
+ "message_body TEXT," + // message body
+ "display_originating_addr TEXT);");// display address
}
@Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java
index 4c8ccc10e..a036c621e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/InboundSmsTrackerTest.java
@@ -34,6 +34,7 @@ public class InboundSmsTrackerTest {
private static final long FAKE_TIMESTAMP = 123456L;
private static final int FAKE_DEST_PORT = 1234;
private static final String FAKE_ADDRESS = "address";
+ private static final String FAKE_DISPLAY_ADDRESS = "disp_addr";
private static final int FAKE_REFERENCE_NUMBER = 345;
private static final int FAKE_SEQUENCE_NUMBER = 3;
private static final int FAKE_MESSAGE_COUNT = 5;
@@ -42,19 +43,22 @@ public class InboundSmsTrackerTest {
@Before
public void setUp() throws Exception {
mInboundSmsTracker = new InboundSmsTracker(FAKE_PDU, FAKE_TIMESTAMP, FAKE_DEST_PORT, false,
- FAKE_ADDRESS, FAKE_REFERENCE_NUMBER, FAKE_SEQUENCE_NUMBER, FAKE_MESSAGE_COUNT,
- false, FAKE_MESSAGE_BODY);
+ FAKE_ADDRESS, FAKE_DISPLAY_ADDRESS, FAKE_REFERENCE_NUMBER, FAKE_SEQUENCE_NUMBER,
+ FAKE_MESSAGE_COUNT, false, FAKE_MESSAGE_BODY);
}
public static MatrixCursor createFakeCursor() {
MatrixCursor mc = new MatrixCursor(
- new String[]{"pdu", "seq", "dest", "date", "ref", "cnt", "addr", "id", "msg_body"});
+ new String[]{"pdu", "seq", "dest", "date", "ref", "cnt", "addr", "id", "msg_body",
+ "display_originating_addr"});
mc.addRow(new Object[]{HexDump.toHexString(FAKE_PDU),
FAKE_SEQUENCE_NUMBER, FAKE_DEST_PORT, FAKE_TIMESTAMP,
- FAKE_REFERENCE_NUMBER, FAKE_MESSAGE_COUNT, FAKE_ADDRESS, 1, FAKE_MESSAGE_BODY});
+ FAKE_REFERENCE_NUMBER, FAKE_MESSAGE_COUNT, FAKE_ADDRESS, 1, FAKE_MESSAGE_BODY,
+ FAKE_DISPLAY_ADDRESS});
mc.addRow(new Object[]{HexDump.toHexString(FAKE_PDU),
FAKE_SEQUENCE_NUMBER, FAKE_DEST_PORT, FAKE_TIMESTAMP,
- FAKE_REFERENCE_NUMBER, FAKE_MESSAGE_COUNT, FAKE_ADDRESS, 2, FAKE_MESSAGE_BODY});
+ FAKE_REFERENCE_NUMBER, FAKE_MESSAGE_COUNT, FAKE_ADDRESS, 2, FAKE_MESSAGE_BODY,
+ FAKE_DISPLAY_ADDRESS});
mc.moveToFirst();
return mc;
}
@@ -73,6 +77,7 @@ public class InboundSmsTrackerTest {
assertEquals(1, mInboundSmsTracker.getIndexOffset());
assertEquals(SmsConstants.FORMAT_3GPP, mInboundSmsTracker.getFormat());
assertEquals(FAKE_MESSAGE_BODY, mInboundSmsTracker.getMessageBody());
+ assertEquals(FAKE_DISPLAY_ADDRESS, mInboundSmsTracker.getDisplayAddress());
String[] args = new String[]{"123"};
mInboundSmsTracker.setDeleteWhere(InboundSmsHandler.SELECT_BY_ID, args);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 805ee931f..30c8d032f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -329,10 +329,11 @@ public abstract class TelephonyTest {
.makeWspTypeDecoder(any(byte[].class));
doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyBoolean(), anyString(), anyString());
+ anyBoolean(), anyString(), anyString(), anyString());
doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(Cursor.class), anyBoolean());
doReturn(mImsCT).when(mTelephonyComponentFactory)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
index 652f18fe4..8bc881ef7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
@@ -212,7 +212,7 @@ public class CdmaInboundSmsHandlerTest extends TelephonyTest {
@MediumTest
public void testNewSmsFromBlockedNumber_noBroadcastsSent() {
String blockedNumber = "123456789";
- doReturn(blockedNumber).when(mInboundSmsTracker).getAddress();
+ doReturn(blockedNumber).when(mInboundSmsTracker).getDisplayAddress();
mFakeBlockedNumberContentProvider.mBlockedNumbers.add(blockedNumber);
transitionFromStartupToIdle();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
index 4e03553b5..92d8c34fc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnSettingTest.java
@@ -28,13 +28,23 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
+import static com.android.internal.telephony.PhoneConstants.APN_TYPE_ALL;
+import static com.android.internal.telephony.PhoneConstants.APN_TYPE_DEFAULT;
+import static com.android.internal.telephony.PhoneConstants.APN_TYPE_HIPRI;
+import static com.android.internal.telephony.PhoneConstants.APN_TYPE_IA;
+import static com.android.internal.telephony.PhoneConstants.APN_TYPE_MMS;
+import static com.android.internal.telephony.PhoneConstants.APN_TYPE_SUPL;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
+
public class ApnSettingTest extends TelephonyTest {
private PersistableBundle mBundle;
@@ -52,6 +62,14 @@ public class ApnSettingTest extends TelephonyTest {
}
private ApnSetting createApnSetting(String[] apnTypes) {
+ return createApnSettingInternal(apnTypes, true);
+ }
+
+ private ApnSetting createDisabledApnSetting(String[] apnTypes) {
+ return createApnSettingInternal(apnTypes, false);
+ }
+
+ private ApnSetting createApnSettingInternal(String[] apnTypes, boolean carrierEnabled) {
return new ApnSetting(
2163, // id
"44010", // numeric
@@ -68,7 +86,7 @@ public class ApnSettingTest extends TelephonyTest {
apnTypes, // types
"IP", // protocol
"IP", // roaming_protocol
- true, // carrier_enabled
+ carrierEnabled, // carrier_enabled
0, // bearer
0, // bearer_bitmask
0, // profile_id
@@ -243,7 +261,6 @@ public class ApnSettingTest extends TelephonyTest {
new String[]{PhoneConstants.APN_TYPE_IA, PhoneConstants.APN_TYPE_CBS}).
isMetered(mContext, 1, isRoaming));
- //reuse the cached result for subId 1
assertTrue(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_DEFAULT,
mContext, 1, isRoaming));
assertTrue(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_MMS,
@@ -260,6 +277,15 @@ public class ApnSettingTest extends TelephonyTest {
mContext, 1, isRoaming));
assertFalse(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_HIPRI,
mContext, 1, isRoaming));
+
+ // Carrier config settings changes.
+ mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
+ new String[]{PhoneConstants.APN_TYPE_DEFAULT});
+
+ assertTrue(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_DEFAULT,
+ mContext, 1, isRoaming));
+ assertFalse(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_MMS,
+ mContext, 1, isRoaming));
}
@Test
@@ -300,6 +326,17 @@ public class ApnSettingTest extends TelephonyTest {
assertFalse(createApnSetting(
new String[]{PhoneConstants.APN_TYPE_IA, PhoneConstants.APN_TYPE_CBS}).
isMetered(mContext, 1, isRoaming));
+
+ // Carrier config settings changes.
+ mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
+ new String[]{PhoneConstants.APN_TYPE_FOTA});
+
+ assertFalse(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_DEFAULT,
+ mContext, 1, isRoaming));
+ assertFalse(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_MMS,
+ mContext, 1, isRoaming));
+ assertTrue(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_FOTA,
+ mContext, 1, isRoaming));
}
@Test
@@ -380,7 +417,6 @@ public class ApnSettingTest extends TelephonyTest {
new String[]{PhoneConstants.APN_TYPE_IMS}).
isMetered(mContext, 2, isRoaming));
- //reuse the cached result for subId 2
assertTrue(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_SUPL,
mContext, 2, isRoaming));
assertTrue(ApnSetting.isMeteredApnType(PhoneConstants.APN_TYPE_CBS,
@@ -493,6 +529,102 @@ public class ApnSettingTest extends TelephonyTest {
assertTrue(createApnSetting(
new String[]{PhoneConstants.APN_TYPE_IA, PhoneConstants.APN_TYPE_DUN}).
isMetered(mContext, 4, isRoaming));
+ }
+ @Test
+ @SmallTest
+ public void testCanHandleType() throws Exception {
+ String types[] = {"mms"};
+
+ // empty string replaced with ALL ('*') when loaded to db
+ assertFalse(createApnSetting(new String[]{}).
+ canHandleType(APN_TYPE_MMS));
+
+ assertTrue(createApnSetting(new String[]{APN_TYPE_ALL}).
+ canHandleType(APN_TYPE_MMS));
+
+ assertFalse(createApnSetting(new String[]{APN_TYPE_DEFAULT}).
+ canHandleType(APN_TYPE_MMS));
+
+ assertTrue(createApnSetting(new String[]{"DEfAULT"}).
+ canHandleType("defAult"));
+
+ // Hipri is asymmetric
+ assertTrue(createApnSetting(new String[]{APN_TYPE_DEFAULT}).
+ canHandleType(APN_TYPE_HIPRI));
+ assertFalse(createApnSetting(new String[]{APN_TYPE_HIPRI}).
+ canHandleType(APN_TYPE_DEFAULT));
+
+
+ assertTrue(createApnSetting(new String[]{APN_TYPE_DEFAULT, APN_TYPE_MMS}).
+ canHandleType(APN_TYPE_DEFAULT));
+
+ assertTrue(createApnSetting(new String[]{APN_TYPE_DEFAULT, APN_TYPE_MMS}).
+ canHandleType(APN_TYPE_MMS));
+
+ assertFalse(createApnSetting(new String[]{APN_TYPE_DEFAULT, APN_TYPE_MMS}).
+ canHandleType(APN_TYPE_SUPL));
+
+ // special IA case - doesn't match wildcards
+ assertFalse(createApnSetting(new String[]{APN_TYPE_DEFAULT, APN_TYPE_MMS}).
+ canHandleType(APN_TYPE_IA));
+ assertFalse(createApnSetting(new String[]{APN_TYPE_ALL}).
+ canHandleType(APN_TYPE_IA));
+ assertFalse(createApnSetting(new String[]{APN_TYPE_ALL}).
+ canHandleType("iA"));
+ assertTrue(createApnSetting(new String[]{APN_TYPE_DEFAULT, APN_TYPE_MMS, APN_TYPE_IA}).
+ canHandleType(APN_TYPE_IA));
+
+ // check carrier disabled
+ assertFalse(createDisabledApnSetting(new String[]{APN_TYPE_ALL}).
+ canHandleType(APN_TYPE_MMS));
+ assertFalse(createDisabledApnSetting(new String[]{"DEfAULT"}).
+ canHandleType("defAult"));
+ assertFalse(createDisabledApnSetting(new String[]{APN_TYPE_DEFAULT}).
+ canHandleType(APN_TYPE_HIPRI));
+ assertFalse(createDisabledApnSetting(new String[]{APN_TYPE_DEFAULT, APN_TYPE_MMS}).
+ canHandleType(APN_TYPE_DEFAULT));
+ assertFalse(createDisabledApnSetting(new String[]{APN_TYPE_DEFAULT, APN_TYPE_MMS}).
+ canHandleType(APN_TYPE_MMS));
+ assertFalse(createDisabledApnSetting(new String[]
+ {APN_TYPE_DEFAULT, APN_TYPE_MMS, APN_TYPE_IA}).
+ canHandleType(APN_TYPE_IA));
+ }
+
+ @Test
+ @SmallTest
+ public void testEquals() throws Exception {
+ final int dummyInt = 1;
+ final String dummyString = "dummy";
+ final String[] dummyStringArr = new String[] {"dummy"};
+ // base apn
+ ApnSetting baseApn = createApnSetting(new String[] {"mms", "default"});
+ Field[] fields = ApnSetting.class.getDeclaredFields();
+ for (Field f : fields) {
+ int modifiers = f.getModifiers();
+ if (Modifier.isStatic(modifiers) || !Modifier.isFinal(modifiers)) {
+ continue;
+ }
+ f.setAccessible(true);
+ ApnSetting testApn = null;
+ if (int.class.equals(f.getType())) {
+ testApn = new ApnSetting(baseApn);
+ f.setInt(testApn, dummyInt + f.getInt(testApn));
+ } else if (boolean.class.equals(f.getType())) {
+ testApn = new ApnSetting(baseApn);
+ f.setBoolean(testApn, !f.getBoolean(testApn));
+ } else if (String.class.equals(f.getType())) {
+ testApn = new ApnSetting(baseApn);
+ f.set(testApn, dummyString);
+ } else if (String[].class.equals(f.getType())) {
+ testApn = new ApnSetting(baseApn);
+ f.set(testApn, dummyStringArr);
+ } else {
+ fail("Unsupported field:" + f.getName());
+ }
+ if (testApn != null) {
+ assertFalse(f.getName() + " is NOT checked", testApn.equals(baseApn));
+ }
+ }
}
-} \ No newline at end of file
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
index 41415ecc2..6d44d029a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
@@ -144,6 +144,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
mInboundSmsTrackerCV.put("count", 1);
mInboundSmsTrackerCV.put("date", System.currentTimeMillis());
mInboundSmsTrackerCV.put("message_body", mMessageBody);
+ mInboundSmsTrackerCV.put("display_originating_addr", "1234567890");
doReturn(1).when(mInboundSmsTracker).getMessageCount();
doReturn(1).when(mInboundSmsTracker).getReferenceNumber();
@@ -272,8 +273,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
@Test
@MediumTest
public void testNewSmsFromBlockedNumber_noBroadcastsSent() {
- String blockedNumber = "123456789";
- doReturn(blockedNumber).when(mInboundSmsTracker).getAddress();
+ String blockedNumber = "1234567890";
+ doReturn(blockedNumber).when(mInboundSmsTracker).getDisplayAddress();
mFakeBlockedNumberContentProvider.mBlockedNumbers.add(blockedNumber);
transitionFromStartupToIdle();
@@ -351,6 +352,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
mInboundSmsTrackerCVPart1.put("count", 2);
mInboundSmsTrackerCVPart1.put("date", System.currentTimeMillis());
mInboundSmsTrackerCVPart1.put("message_body", mMessageBodyPart1);
+ mInboundSmsTrackerCVPart1.put("display_originating_addr", "1234567890");
doReturn(2).when(mInboundSmsTrackerPart1).getMessageCount();
doReturn(1).when(mInboundSmsTrackerPart1).getReferenceNumber();
@@ -374,6 +376,7 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
mInboundSmsTrackerCVPart2.put("count", 2);
mInboundSmsTrackerCVPart2.put("date", System.currentTimeMillis());
mInboundSmsTrackerCVPart2.put("message_body", mMessageBodyPart2);
+ mInboundSmsTrackerCVPart2.put("display_originating_addr", "1234567890");
doReturn(2).when(mInboundSmsTrackerPart2).getMessageCount();
doReturn(1).when(mInboundSmsTrackerPart2).getReferenceNumber();
@@ -402,7 +405,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
waitForMs(100);
@@ -412,7 +416,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
waitForMs(100);
@@ -427,7 +432,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
// additional copy of part 2 of message
doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
waitForMs(100);
@@ -444,7 +450,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
// part 1 of new sms
doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
waitForMs(100);
@@ -475,7 +482,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
waitForMs(100);
@@ -485,7 +493,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
waitForMs(100);
@@ -512,7 +521,8 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
doReturn(mSmsHeader).when(mGsmSmsMessage).getUserDataHeader();
doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
@@ -523,7 +533,46 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory)
.makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
- anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString());
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
+ mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
+ mSmsMessage, null));
+ waitForMs(100);
+
+ verify(mContext, never()).sendBroadcast(any(Intent.class));
+ assertEquals("IdleState", getCurrentState().getName());
+ }
+
+ @Test
+ @MediumTest
+ public void testMultipartSmsFromBlockedEmail_noBroadcastsSent() {
+ mFakeBlockedNumberContentProvider.mBlockedNumbers.add("1234567890@test.com");
+
+ transitionFromStartupToIdle();
+
+ // prepare SMS part 1 and part 2
+ prepareMultiPartSms();
+ // only the first SMS is configured with the display originating email address
+ mInboundSmsTrackerCVPart1.put("display_originating_addr", "1234567890@test.com");
+
+ mSmsHeader.concatRef = new SmsHeader.ConcatRef();
+ doReturn(mSmsHeader).when(mGsmSmsMessage).getUserDataHeader();
+ doReturn(mInboundSmsTrackerPart1).when(mTelephonyComponentFactory)
+ .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
+
+ mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
+ mSmsMessage, null));
+ waitForMs(100);
+
+ // State machine should go back to idle and wait for second part
+ assertEquals("IdleState", getCurrentState().getName());
+
+ doReturn(mInboundSmsTrackerPart2).when(mTelephonyComponentFactory)
+ .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(),
+ anyString(), anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(),
+ anyString());
mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS, new AsyncResult(null,
mSmsMessage, null));
waitForMs(100);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
index c8517a259..8eaefb6dd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
@@ -248,8 +248,6 @@ public class ImsPhoneConnectionTest extends TelephonyTest {
ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN + "");
assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE));
assertTrue(mConnectionUT.isWifi());
- //keep using the wifi state from extra, not update
- assertFalse(mConnectionUT.updateWifiState());
}
@Test
@@ -265,7 +263,5 @@ public class ImsPhoneConnectionTest extends TelephonyTest {
ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN + "");
assertTrue(mConnectionUT.update(mImsCall, Call.State.ACTIVE));
assertTrue(mConnectionUT.isWifi());
- //keep using the wifi state from extra, not update
- assertFalse(mConnectionUT.updateWifiState());
}
}
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 810533519..572cf41fe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/TelephonyMetricsTest.java
@@ -24,6 +24,7 @@ import com.android.ims.ImsConfig;
import com.android.ims.ImsReasonInfo;
import com.android.ims.internal.ImsCallSession;
import com.android.internal.telephony.Call;
+import com.android.internal.telephony.GsmCdmaConnection;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.SmsResponse;
import com.android.internal.telephony.TelephonyProto;
@@ -33,6 +34,7 @@ import com.android.internal.telephony.TelephonyProto.RadioAccessTechnology;
import com.android.internal.telephony.TelephonyProto.TelephonyCallSession;
import com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.CallState;
import com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.ImsCommand;
+import com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.RilCall;
import com.android.internal.telephony.TelephonyProto.TelephonyEvent;
import com.android.internal.telephony.TelephonyProto.TelephonyLog;
import com.android.internal.telephony.TelephonyProto.TelephonyServiceState;
@@ -71,6 +73,9 @@ public class TelephonyMetricsTest extends TelephonyTest {
@Mock
private ServiceState mServiceState;
+ @Mock
+ private GsmCdmaConnection mConnection;
+
private TelephonyMetrics mMetrics;
private UUSInfo mUusInfo;
@@ -460,8 +465,10 @@ public class TelephonyMetricsTest extends TelephonyTest {
@Test
@SmallTest
public void testWriteRilDialHangup() throws Exception {
- mMetrics.writeRilDial(mPhone.getPhoneId(), 1, 2, mUusInfo);
- mMetrics.writeRilHangup(mPhone.getPhoneId(), 2, 3);
+ doReturn(Call.State.DIALING).when(mConnection).getState();
+ mMetrics.writeRilDial(mPhone.getPhoneId(), mConnection, 2, mUusInfo);
+ doReturn(Call.State.DISCONNECTED).when(mConnection).getState();
+ mMetrics.writeRilHangup(mPhone.getPhoneId(), mConnection, 3);
mMetrics.writePhoneState(mPhone.getPhoneId(), PhoneConstants.State.IDLE);
TelephonyLog log = buildProto();
@@ -479,16 +486,18 @@ public class TelephonyMetricsTest extends TelephonyTest {
assertTrue(events[0].hasRilRequest());
assertEquals(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_DIAL,
events[0].getRilRequest());
- assertTrue(events[0].hasRilRequestId());
- assertEquals(1, events[0].getRilRequestId());
+ RilCall[] calls = events[0].calls;
+ assertEquals(CallState.CALL_DIALING, calls[0].getState());
assertTrue(events[1].hasType());
assertEquals(TelephonyCallSession.Event.Type.RIL_REQUEST, events[1].getType());
assertTrue(events[1].hasRilRequest());
assertEquals(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_HANGUP,
events[1].getRilRequest());
- assertTrue(events[1].hasCallIndex());
- assertEquals(3, events[1].getCallIndex());
+ calls = events[1].calls;
+ assertTrue(calls[0].hasIndex());
+ assertEquals(3, calls[0].getIndex());
+ assertEquals(CallState.CALL_DISCONNECTED, calls[0].getState());
}
// Test write RIL setup data call
@@ -612,4 +621,4 @@ public class TelephonyMetricsTest extends TelephonyTest {
byte[] decodedString = Base64.decode(encodedString, Base64.DEFAULT);
assertArrayEquals(TelephonyProto.TelephonyLog.toByteArray(log), decodedString);
}
-} \ No newline at end of file
+}