aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-11-28 23:51:17 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-11-28 23:51:17 +0000
commit63eb6ad287546db3afab23c2360da649424e2d35 (patch)
tree1343a07368deb3a742de8a228e3ab97f070b5ed1
parentc6f499e4a2242fcbb185cd615debc32320ec0579 (diff)
parent551e63a25455174ee5da8bf7d9439c4046ca8f38 (diff)
downloadtelephony-oreo-m3-release.tar.gz
Change-Id: Ided9fdd740a1b2f5afb2863b9214779c3e37220f
-rw-r--r--Android.mk2
-rw-r--r--src/java/com/android/internal/telephony/CallForwardInfo.java12
-rw-r--r--src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java192
-rw-r--r--src/java/com/android/internal/telephony/CarrierServiceStateTracker.java9
-rw-r--r--src/java/com/android/internal/telephony/ClientWakelockTracker.java12
-rw-r--r--src/java/com/android/internal/telephony/DefaultPhoneNotifier.java3
-rw-r--r--src/java/com/android/internal/telephony/GsmCdmaPhone.java3
-rw-r--r--src/java/com/android/internal/telephony/InboundSmsHandler.java47
-rw-r--r--src/java/com/android/internal/telephony/Phone.java6
-rw-r--r--src/java/com/android/internal/telephony/RIL.java2
-rw-r--r--src/java/com/android/internal/telephony/ServiceStateTracker.java42
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhone.java1
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java3
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java22
-rw-r--r--src/java/com/android/internal/telephony/util/NotificationChannelController.java13
-rw-r--r--tests/telephonytests/Android.mk2
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java321
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java4
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java18
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java26
20 files changed, 641 insertions, 99 deletions
diff --git a/Android.mk b/Android.mk
index 70a88db7c5..b440b28dcf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -25,7 +25,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src/java) \
$(call all-logtags-files-under, src/java) \
$(call all-proto-files-under, proto)
-LOCAL_JAVA_LIBRARIES := voip-common ims-common services
+LOCAL_JAVA_LIBRARIES := voip-common ims-common services bouncycastle
LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.radio-V1.1-java-static \
android.hardware.radio.deprecated-V1.0-java-static
diff --git a/src/java/com/android/internal/telephony/CallForwardInfo.java b/src/java/com/android/internal/telephony/CallForwardInfo.java
index dccf3066a9..e40028fc28 100644
--- a/src/java/com/android/internal/telephony/CallForwardInfo.java
+++ b/src/java/com/android/internal/telephony/CallForwardInfo.java
@@ -16,12 +16,16 @@
package com.android.internal.telephony;
+import android.telecom.Log;
+
/**
* See also RIL_CallForwardInfo in include/telephony/ril.h
*
* {@hide}
*/
public class CallForwardInfo {
+ private static final String TAG = "CallForwardInfo";
+
public int status; /*1 = active, 0 = not active */
public int reason; /* from TS 27.007 7.11 "reason" */
public int serviceClass; /* Saum of CommandsInterface.SERVICE_CLASS */
@@ -31,9 +35,9 @@ public class CallForwardInfo {
@Override
public String toString() {
- return super.toString() + (status == 0 ? " not active " : " active ")
- + " reason: " + reason
- + " serviceClass: " + serviceClass + " " + timeSeconds + " seconds";
-
+ return "[CallForwardInfo: status=" + (status == 0 ? " not active " : " active ")
+ + ", reason= " + reason
+ + ", serviceClass= " + serviceClass + ", timeSec= " + timeSeconds + " seconds"
+ + ", number=" + Log.pii(number) + "]";
}
}
diff --git a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
index bca337d81c..66bc529114 100644
--- a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
+++ b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
@@ -18,6 +18,8 @@ package com.android.internal.telephony;
import static android.preference.PreferenceManager.getDefaultSharedPreferences;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import android.app.AlarmManager;
import android.app.DownloadManager;
import android.app.PendingIntent;
@@ -34,21 +36,28 @@ import android.telephony.ImsiEncryptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.Base64;
import android.util.Log;
+import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.org.bouncycastle.util.io.pem.PemReader;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.Reader;
+import java.security.PublicKey;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.util.Date;
+import java.util.zip.GZIPInputStream;
/**
* This class contains logic to get Certificates and keep them current.
@@ -68,16 +77,19 @@ public class CarrierKeyDownloadManager {
private static final String INTENT_KEY_RENEWAL_ALARM_PREFIX =
"com.android.internal.telephony.carrier_key_download_alarm";
- private int mKeyAvailability = 0;
+ @VisibleForTesting
+ public int mKeyAvailability = 0;
public static final String MNC = "MNC";
public static final String MCC = "MCC";
private static final String SEPARATOR = ":";
- private static final String JSON_KEY = "key";
- private static final String JSON_TYPE = "type";
- private static final String JSON_IDENTIFIER = "identifier";
- private static final String JSON_EXPIRATION_DATE = "expiration-date";
+ private static final String JSON_CERTIFICATE = "certificate";
+ // This is a hack to accommodate certain Carriers who insists on using the public-key
+ // field to store the certificate. We'll just use which-ever is not null.
+ private static final String JSON_CERTIFICATE_ALTERNATE = "public-key";
+ private static final String JSON_TYPE = "key-type";
+ private static final String JSON_IDENTIFIER = "key-identifier";
private static final String JSON_CARRIER_KEYS = "carrier-keys";
private static final String JSON_TYPE_VALUE_WLAN = "WLAN";
private static final String JSON_TYPE_VALUE_EPDG = "EPDG";
@@ -89,7 +101,7 @@ public class CarrierKeyDownloadManager {
private final Phone mPhone;
private final Context mContext;
- private final DownloadManager mDownloadManager;
+ public final DownloadManager mDownloadManager;
private String mURL;
public CarrierKeyDownloadManager(Phone phone) {
@@ -173,14 +185,11 @@ public class CarrierKeyDownloadManager {
}
/**
- * this method resets the alarm. Starts by cleaning up the existing alarms.
- * We look at the earliest expiration date, and setup an alarms X days prior.
- * If the expiration date is in the past, we'll setup an alarm to run the next day. This
- * could happen if the download has failed.
+ * this method returns the date to be used to decide on when to start downloading the key.
+ * from the carrier.
**/
- private void resetRenewalAlarm() {
- cleanupRenewalAlarms();
- int slotId = mPhone.getPhoneId();
+ @VisibleForTesting
+ public long getExpirationDate() {
long minExpirationDate = Long.MAX_VALUE;
for (int key_type : CARRIER_KEY_TYPES) {
if (!isKeyEnabled(key_type)) {
@@ -204,6 +213,20 @@ public class CarrierKeyDownloadManager {
} else {
minExpirationDate = minExpirationDate - DEFAULT_RENEWAL_WINDOW_DAYS * DAY_IN_MILLIS;
}
+ return minExpirationDate;
+ }
+
+ /**
+ * this method resets the alarm. Starts by cleaning up the existing alarms.
+ * We look at the earliest expiration date, and setup an alarms X days prior.
+ * If the expiration date is in the past, we'll setup an alarm to run the next day. This
+ * could happen if the download has failed.
+ **/
+ @VisibleForTesting
+ public void resetRenewalAlarm() {
+ cleanupRenewalAlarms();
+ int slotId = mPhone.getPhoneId();
+ long minExpirationDate = getExpirationDate();
Log.d(LOG_TAG, "minExpirationDate: " + new Date(minExpirationDate));
final AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(
Context.ALARM_SERVICE);
@@ -225,21 +248,30 @@ public class CarrierKeyDownloadManager {
}
/**
+ * Returns the sim operator.
+ **/
+ @VisibleForTesting
+ public String getSimOperator() {
+ final TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ return telephonyManager.getSimOperator(mPhone.getSubId());
+ }
+
+ /**
* checks if the download was sent by this particular instance. We do this by including the
* slot id in the key. If no value is found, we know that the download was not for this
* instance of the phone.
**/
- private boolean isValidDownload(String mccMnc) {
+ @VisibleForTesting
+ public boolean isValidDownload(String mccMnc) {
String mccCurrent = "";
String mncCurrent = "";
String mccSource = "";
String mncSource = "";
- final TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- String networkOperator = telephonyManager.getNetworkOperator(mPhone.getSubId());
- if (TextUtils.isEmpty(networkOperator) || TextUtils.isEmpty(mccMnc)) {
- Log.e(LOG_TAG, "networkOperator or mcc/mnc is empty");
+ String simOperator = getSimOperator();
+ if (TextUtils.isEmpty(simOperator) || TextUtils.isEmpty(mccMnc)) {
+ Log.e(LOG_TAG, "simOperator or mcc/mnc is empty");
return false;
}
@@ -248,8 +280,8 @@ public class CarrierKeyDownloadManager {
mncSource = splitValue[1];
Log.d(LOG_TAG, "values from sharedPrefs mcc, mnc: " + mccSource + "," + mncSource);
- mccCurrent = networkOperator.substring(0, 3);
- mncCurrent = networkOperator.substring(3);
+ mccCurrent = simOperator.substring(0, 3);
+ mncCurrent = simOperator.substring(3);
Log.d(LOG_TAG, "using values for mcc, mnc: " + mccCurrent + "," + mncCurrent);
if (TextUtils.equals(mncSource, mncCurrent) && TextUtils.equals(mccSource, mccCurrent)) {
@@ -267,6 +299,7 @@ public class CarrierKeyDownloadManager {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(carrierKeyDownloadIdentifier);
Cursor cursor = mDownloadManager.query(query);
+ InputStream source = null;
if (cursor == null) {
return;
@@ -275,7 +308,7 @@ public class CarrierKeyDownloadManager {
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == cursor.getInt(columnIndex)) {
try {
- final InputStream source = new FileInputStream(
+ source = new FileInputStream(
mDownloadManager.openDownloadedFile(carrierKeyDownloadIdentifier)
.getFileDescriptor());
jsonStr = convertToString(source);
@@ -285,6 +318,11 @@ public class CarrierKeyDownloadManager {
+ ". " + e);
} finally {
mDownloadManager.remove(carrierKeyDownloadIdentifier);
+ try {
+ source.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
Log.d(LOG_TAG, "Completed downloading keys");
@@ -324,43 +362,43 @@ public class CarrierKeyDownloadManager {
}
private static String convertToString(InputStream is) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(is));
- StringBuilder sb = new StringBuilder();
-
- String line;
try {
+ // The current implementation at certain Carriers has the data gzipped, which requires
+ // us to unzip the contents. Longer term, we want to add a flag in carrier config which
+ // determines if the data needs to be zipped or not.
+ GZIPInputStream gunzip = new GZIPInputStream(is);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(gunzip, UTF_8));
+ StringBuilder sb = new StringBuilder();
+
+ String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append('\n');
}
+ return sb.toString();
} catch (IOException e) {
e.printStackTrace();
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
}
- return sb.toString();
+ return null;
}
/**
* Converts the string into a json object to retreive the nodes. The Json should have 3 nodes,
* including the Carrier public key, the key type and the key identifier. Once the nodes have
* been extracted, they get persisted to the database. Sample:
- * "carrier-keys": [ { "key": "",
- * "type": WLAN,
- * "identifier": "",
- * "expiration-date": 1502577746000
+ * "carrier-keys": [ { "certificate": "",
+ * "key-type": "WLAN",
+ * "key-identifier": ""
* } ]
* @param jsonStr the json string.
- * @param mccMnc contains the mcc, mnc
+ * @param mccMnc contains the mcc, mnc.
*/
- private void parseJsonAndPersistKey(String jsonStr, String mccMnc) {
+ @VisibleForTesting
+ public void parseJsonAndPersistKey(String jsonStr, String mccMnc) {
if (TextUtils.isEmpty(jsonStr) || TextUtils.isEmpty(mccMnc)) {
Log.e(LOG_TAG, "jsonStr or mcc, mnc: is empty");
return;
}
+ PemReader reader = null;
try {
String mcc = "";
String mnc = "";
@@ -369,10 +407,16 @@ public class CarrierKeyDownloadManager {
mnc = splitValue[1];
JSONObject jsonObj = new JSONObject(jsonStr);
JSONArray keys = jsonObj.getJSONArray(JSON_CARRIER_KEYS);
-
for (int i = 0; i < keys.length(); i++) {
JSONObject key = keys.getJSONObject(i);
- String carrierKey = key.getString(JSON_KEY);
+ // This is a hack to accommodate certain carriers who insist on using the public-key
+ // field to store the certificate. We'll just use which-ever is not null.
+ String cert = null;
+ if (key.has(JSON_CERTIFICATE)) {
+ cert = key.getString(JSON_CERTIFICATE);
+ } else {
+ cert = key.getString(JSON_CERTIFICATE_ALTERNATE);
+ }
String typeString = key.getString(JSON_TYPE);
int type = UNINITIALIZED_KEY_TYPE;
if (typeString.equals(JSON_TYPE_VALUE_WLAN)) {
@@ -380,13 +424,27 @@ public class CarrierKeyDownloadManager {
} else if (typeString.equals(JSON_TYPE_VALUE_EPDG)) {
type = TelephonyManager.KEY_TYPE_EPDG;
}
- long expiration_date = key.getLong(JSON_EXPIRATION_DATE);
String identifier = key.getString(JSON_IDENTIFIER);
- savePublicKey(carrierKey, type, identifier, expiration_date,
- mcc, mnc);
+ ByteArrayInputStream inStream = new ByteArrayInputStream(cert.getBytes());
+ Reader fReader = new BufferedReader(new InputStreamReader(inStream));
+ reader = new PemReader(fReader);
+ Pair<PublicKey, Long> keyInfo =
+ getKeyInformation(reader.readPemObject().getContent());
+ reader.close();
+ savePublicKey(keyInfo.first, type, identifier, keyInfo.second, mcc, mnc);
}
} catch (final JSONException e) {
Log.e(LOG_TAG, "Json parsing error: " + e.getMessage());
+ } catch (final Exception e) {
+ Log.e(LOG_TAG, "Exception getting certificate: " + e);
+ } finally {
+ try {
+ if (reader != null) {
+ reader.close();
+ }
+ } catch (final Exception e) {
+ Log.e(LOG_TAG, "Exception getting certificate: " + e);
+ }
}
}
@@ -394,8 +452,8 @@ public class CarrierKeyDownloadManager {
* introspects the mKeyAvailability bitmask
* @return true if the digit at position k is 1, else false.
*/
-
- private boolean isKeyEnabled(int keyType) {
+ @VisibleForTesting
+ public boolean isKeyEnabled(int keyType) {
//since keytype has values of 1, 2.... we need to subtract 1 from the keytype.
int returnValue = (mKeyAvailability >> (keyType - 1)) & 1;
return (returnValue == 1) ? true : false;
@@ -427,15 +485,13 @@ public class CarrierKeyDownloadManager {
private boolean downloadKey() {
Log.d(LOG_TAG, "starting download from: " + mURL);
- final TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
String mcc = "";
String mnc = "";
- String networkOperator = telephonyManager.getNetworkOperator(mPhone.getSubId());
+ String simOperator = getSimOperator();
- if (!TextUtils.isEmpty(networkOperator)) {
- mcc = networkOperator.substring(0, 3);
- mnc = networkOperator.substring(3);
+ if (!TextUtils.isEmpty(simOperator)) {
+ mcc = simOperator.substring(0, 3);
+ mnc = simOperator.substring(3);
Log.d(LOG_TAG, "using values for mcc, mnc: " + mcc + "," + mnc);
} else {
Log.e(LOG_TAG, "mcc, mnc: is empty");
@@ -461,11 +517,35 @@ public class CarrierKeyDownloadManager {
return true;
}
- private void savePublicKey(String key, int type, String identifier, long expirationDate,
+ /**
+ * Save the public key
+ * @param certificate certificate that contains the public key.
+ * @return Pair containing the Public Key and the expiration date.
+ **/
+ @VisibleForTesting
+ public static Pair<PublicKey, Long> getKeyInformation(byte[] certificate) throws Exception {
+ InputStream inStream = new ByteArrayInputStream(certificate);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
+ Pair<PublicKey, Long> keyInformation =
+ new Pair(cert.getPublicKey(), cert.getNotAfter().getTime());
+ return keyInformation;
+ }
+
+ /**
+ * Save the public key
+ * @param publicKey public key.
+ * @param type key-type.
+ * @param identifier which is an opaque string.
+ * @param expirationDate expiration date of the key.
+ * @param mcc
+ * @param mnc
+ **/
+ @VisibleForTesting
+ public void savePublicKey(PublicKey publicKey, int type, String identifier, long expirationDate,
String mcc, String mnc) {
- byte[] keyBytes = Base64.decode(key.getBytes(), Base64.DEFAULT);
ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo(mcc, mnc, type, identifier,
- keyBytes, new Date(expirationDate));
+ publicKey, new Date(expirationDate));
mPhone.setCarrierInfoForImsiEncryption(imsiEncryptionInfo);
}
}
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index 8df201e583..77a39eb902 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -79,13 +79,8 @@ public class CarrierServiceStateTracker extends Handler {
switch (msg.what) {
case CARRIER_EVENT_VOICE_REGISTRATION:
case CARRIER_EVENT_DATA_REGISTRATION:
- handleConfigChanges();
- break;
case CARRIER_EVENT_VOICE_DEREGISTRATION:
case CARRIER_EVENT_DATA_DEREGISTRATION:
- if (isRadioOffOrAirplaneMode()) {
- break;
- }
handleConfigChanges();
break;
case NOTIFICATION_EMERGENCY_NETWORK:
@@ -317,8 +312,8 @@ public class CarrierServiceStateTracker extends Handler {
Rlog.i(LOG_TAG, "PrefNetworkNotification: sendMessage() w/values: "
+ "," + isPhoneStillRegistered() + "," + mDelay + "," + isGlobalMode()
+ "," + mSST.isRadioOn());
- if (mDelay == UNINITIALIZED_DELAY_VALUE || isPhoneStillRegistered()
- || isGlobalMode()) {
+ if (mDelay == UNINITIALIZED_DELAY_VALUE || isPhoneStillRegistered() || isGlobalMode()
+ || isRadioOffOrAirplaneMode()) {
return false;
}
return true;
diff --git a/src/java/com/android/internal/telephony/ClientWakelockTracker.java b/src/java/com/android/internal/telephony/ClientWakelockTracker.java
index 5bec60ba2f..fa71e76951 100644
--- a/src/java/com/android/internal/telephony/ClientWakelockTracker.java
+++ b/src/java/com/android/internal/telephony/ClientWakelockTracker.java
@@ -18,10 +18,10 @@ package com.android.internal.telephony;
import android.os.SystemClock;
import android.telephony.ClientRequestStats;
-import android.telephony.Rlog;
import com.android.internal.annotations.VisibleForTesting;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -119,13 +119,13 @@ public class ClientWakelockTracker {
return false;
}
- void dumpClientRequestTracker() {
- Rlog.d(RIL.RILJ_LOG_TAG, "-------mClients---------------");
+ void dumpClientRequestTracker(PrintWriter pw) {
+ pw.println("-------mClients---------------");
synchronized (mClients) {
for (String key : mClients.keySet()) {
- Rlog.d(RIL.RILJ_LOG_TAG, "Client : " + key);
- Rlog.d(RIL.RILJ_LOG_TAG, mClients.get(key).toString());
+ pw.println("Client : " + key);
+ pw.println(mClients.get(key).toString());
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index c13e54086e..98c0a32ecc 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -125,6 +125,9 @@ public class DefaultPhoneNotifier implements PhoneNotifier {
int subId = sender.getSubId();
try {
if (mRegistry != null) {
+ Rlog.d(LOG_TAG, "notifyCallForwardingChanged: subId=" + subId + ", isCFActive="
+ + sender.getCallForwardingIndicator());
+
mRegistry.notifyCallForwardingChangedForSubscriber(subId,
sender.getCallForwardingIndicator());
}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 35a2d41ebb..5053341670 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -1855,6 +1855,8 @@ public class GsmCdmaPhone extends Phone {
@Override
public void setTTYMode(int ttyMode, Message onComplete) {
+ // Send out the TTY Mode change over RIL as well
+ super.setTTYMode(ttyMode, onComplete);
if (mImsPhone != null) {
mImsPhone.setTTYMode(ttyMode, onComplete);
}
@@ -2547,6 +2549,7 @@ public class GsmCdmaPhone extends Phone {
private void processIccRecordEvents(int eventCode) {
switch (eventCode) {
case IccRecords.EVENT_CFI:
+ logi("processIccRecordEvents: EVENT_CFI");
notifyCallForwardingIndicator();
break;
}
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 59195f83ba..391de50019 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -158,6 +158,17 @@ public abstract class InboundSmsHandler extends StateMachine {
/** New SMS received as an AsyncResult. */
public static final int EVENT_INJECT_SMS = 8;
+ /** Update tracker object; used only in waiting state */
+ private static final int EVENT_UPDATE_TRACKER = 9;
+
+ /** Timeout in case state machine is stuck in a state for too long; used only in waiting
+ * state */
+ private static final int EVENT_STATE_TIMEOUT = 10;
+
+ /** Timeout duration for EVENT_STATE_TIMEOUT */
+ @VisibleForTesting
+ public static final int STATE_TIMEOUT = 30000;
+
/** Wakelock release delay when returning to idle state. */
private static final int WAKELOCK_TIMEOUT = 3000;
@@ -450,6 +461,7 @@ public abstract class InboundSmsHandler extends StateMachine {
// if any broadcasts were sent, transition to waiting state
InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj;
if (processMessagePart(inboundSmsTracker)) {
+ sendMessage(EVENT_UPDATE_TRACKER, inboundSmsTracker);
transitionTo(mWaitingState);
} else {
// if event is sent from SmsBroadcastUndelivered.broadcastSms(), and
@@ -493,18 +505,41 @@ public abstract class InboundSmsHandler extends StateMachine {
* {@link IdleState} after any deferred {@link #EVENT_BROADCAST_SMS} messages are handled.
*/
private class WaitingState extends State {
+ private InboundSmsTracker mTracker;
+
+ @Override
+ public void enter() {
+ if (DBG) log("entering Waiting state");
+ mTracker = null;
+ sendMessageDelayed(EVENT_STATE_TIMEOUT, STATE_TIMEOUT);
+ }
+
@Override
public void exit() {
if (DBG) log("exiting Waiting state");
// Before moving to idle state, set wakelock timeout to WAKE_LOCK_TIMEOUT milliseconds
// to give any receivers time to take their own wake locks
setWakeLockTimeout(WAKELOCK_TIMEOUT);
+ if (VDBG) {
+ if (hasMessages(EVENT_STATE_TIMEOUT)) {
+ log("exiting Waiting state: removing EVENT_STATE_TIMEOUT from message queue");
+ }
+ if (hasMessages(EVENT_UPDATE_TRACKER)) {
+ log("exiting Waiting state: removing EVENT_UPDATE_TRACKER from message queue");
+ }
+ }
+ removeMessages(EVENT_STATE_TIMEOUT);
+ removeMessages(EVENT_UPDATE_TRACKER);
}
@Override
public boolean processMessage(Message msg) {
log("WaitingState.processMessage:" + msg.what);
switch (msg.what) {
+ case EVENT_UPDATE_TRACKER:
+ mTracker = (InboundSmsTracker) msg.obj;
+ return HANDLED;
+
case EVENT_BROADCAST_SMS:
// defer until the current broadcast completes
deferMessage(msg);
@@ -520,6 +555,18 @@ public abstract class InboundSmsHandler extends StateMachine {
// not ready to return to idle; ignore
return HANDLED;
+ case EVENT_STATE_TIMEOUT:
+ // stuck in WaitingState for too long; drop the message and exit this state
+ if (mTracker != null) {
+ log("WaitingState.processMessage: EVENT_STATE_TIMEOUT; dropping message");
+ dropSms(new SmsBroadcastReceiver(mTracker));
+ } else {
+ log("WaitingState.processMessage: EVENT_STATE_TIMEOUT; mTracker is null "
+ + "- sending EVENT_BROADCAST_COMPLETE");
+ sendMessage(EVENT_BROADCAST_COMPLETE);
+ }
+ return HANDLED;
+
default:
// parent state handles the other message types
return NOT_HANDLED;
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 28e45565fa..8b0c6775db 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -56,6 +56,7 @@ import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
import android.telephony.VoLteServiceState;
import android.text.TextUtils;
+import android.util.Log;
import com.android.ims.ImsCall;
import com.android.ims.ImsConfig;
@@ -1789,7 +1790,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
int status = enable ? IccRecords.CALL_FORWARDING_STATUS_ENABLED :
IccRecords.CALL_FORWARDING_STATUS_DISABLED;
int subId = getSubId();
- Rlog.d(LOG_TAG, "setCallForwardingIndicatorInSharedPref: Storing status = " + status +
+ Rlog.i(LOG_TAG, "setCallForwardingIndicatorInSharedPref: Storing status = " + status +
" in pref " + CF_STATUS + subId);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
@@ -1831,6 +1832,9 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
if (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_UNKNOWN) {
callForwardingIndicator = getCallForwardingIndicatorFromSharedPref();
}
+ Rlog.v(LOG_TAG, "getCallForwardingIndicator: iccForwardingFlag=" + (r != null
+ ? r.getVoiceCallForwardingFlag() : "null") + ", sharedPrefFlag="
+ + getCallForwardingIndicatorFromSharedPref());
return (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_ENABLED);
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 3ed591f9b4..226ee8e3dc 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -4910,7 +4910,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
pw.println(" mLastNITZTimeInfo=" + Arrays.toString(mLastNITZTimeInfo));
pw.println(" mTestingEmergencyCall=" + mTestingEmergencyCall.get());
- mClientWakelockTracker.dumpClientRequestTracker();
+ mClientWakelockTracker.dumpClientRequestTracker(pw);
}
public List<ClientRequestStats> getClientRequestStats() {
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index e9d6759944..d3c17dd89f 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -210,6 +210,7 @@ public class ServiceStateTracker extends Handler {
protected static final int EVENT_ALL_DATA_DISCONNECTED = 49;
protected static final int EVENT_PHONE_TYPE_SWITCHED = 50;
protected static final int EVENT_RADIO_POWER_FROM_CARRIER = 51;
+ protected static final int EVENT_SIM_NOT_INSERTED = 52;
protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
@@ -354,6 +355,14 @@ public class ServiceStateTracker extends Handler {
}
// update voicemail count and notify message waiting changed
mPhone.updateVoiceMail();
+
+ // cancel notifications if we see SIM_NOT_INSERTED (This happens on bootup before
+ // the SIM is first detected and then subsequently on SIM removals)
+ if (mSubscriptionController.getSlotIndex(subId)
+ == SubscriptionManager.SIM_NOT_INSERTED) {
+ // this is handled on the main thread to mitigate racing with setNotification().
+ sendMessage(obtainMessage(EVENT_SIM_NOT_INSERTED));
+ }
}
}
};
@@ -446,7 +455,6 @@ public class ServiceStateTracker extends Handler {
public static final int CS_NORMAL_ENABLED = 1005; // Access Control blocks normal voice/sms service
public static final int CS_EMERGENCY_ENABLED = 1006; // Access Control blocks emergency call service
public static final int CS_REJECT_CAUSE_ENABLED = 2001; // Notify MM rejection cause
- public static final int CS_REJECT_CAUSE_DISABLED = 2002; // Cancel MM rejection cause
/** Notification id. */
public static final int PS_NOTIFICATION = 888; // Id to update and cancel PS restricted
public static final int CS_NOTIFICATION = 999; // Id to update and cancel CS restricted
@@ -1297,6 +1305,14 @@ public class ServiceStateTracker extends Handler {
}
break;
+ case EVENT_SIM_NOT_INSERTED:
+ if (DBG) log("EVENT_SIM_NOT_INSERTED");
+ cancelAllNotifications();
+ mMdn = null;
+ mMin = null;
+ mIsMinInfoReady = false;
+ break;
+
case EVENT_ALL_DATA_DISCONNECTED:
int dds = SubscriptionManager.getDefaultDataSubscriptionId();
ProxyController.getInstance().unregisterForAllDataDisconnected(dds, this);
@@ -2820,7 +2836,7 @@ public class ServiceStateTracker extends Handler {
}
if (hasRejectCauseChanged) {
- setNotification(mRejectCode == 0 ? CS_REJECT_CAUSE_DISABLED : CS_REJECT_CAUSE_ENABLED);
+ setNotification(CS_REJECT_CAUSE_ENABLED);
}
if (hasChanged) {
@@ -3846,6 +3862,18 @@ public class ServiceStateTracker extends Handler {
}
/**
+ * Cancels all notifications posted to NotificationManager. These notifications for restricted
+ * state and rejection cause for cs registration are no longer valid after the SIM has been
+ * removed.
+ */
+ private void cancelAllNotifications() {
+ if (DBG) log("setNotification: cancelAllNotifications");
+ NotificationManager notificationManager = (NotificationManager)
+ mPhone.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.cancelAll();
+ }
+
+ /**
* Post a notification to NotificationManager for restricted state and
* rejection cause for cs registration
*
@@ -3920,17 +3948,14 @@ public class ServiceStateTracker extends Handler {
notificationId = CS_REJECT_CAUSE_NOTIFICATION;
int resId = selectResourceForRejectCode(mRejectCode);
if (0 == resId) {
- // cancel notification because current reject code is not handled.
- notifyType = CS_REJECT_CAUSE_DISABLED;
+ loge("setNotification: mRejectCode=" + mRejectCode + " is not handled.");
+ return;
} else {
icon = com.android.internal.R.drawable.stat_notify_mmcc_indication_icn;
title = Resources.getSystem().getString(resId);
details = null;
}
break;
- case CS_REJECT_CAUSE_DISABLED:
- notificationId = CS_REJECT_CAUSE_NOTIFICATION;
- break;
}
if (DBG) {
@@ -3954,8 +3979,7 @@ public class ServiceStateTracker extends Handler {
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
- if (notifyType == PS_DISABLED || notifyType == CS_DISABLED
- || notifyType == CS_REJECT_CAUSE_DISABLED) {
+ if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
// cancel previous post notification
notificationManager.cancel(notificationId);
} else {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 3c13a408ae..45dc0b2798 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -713,7 +713,6 @@ public class ImsPhone extends ImsPhoneBase {
@Override
public void setTTYMode(int ttyMode, Message onComplete) {
- super.setTTYMode(ttyMode, onComplete);
mCT.setTtyMode(ttyMode);
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
index 87b96d8b8b..c165b03e3b 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneBase.java
@@ -496,9 +496,6 @@ abstract class ImsPhoneBase extends Phone {
return false;
}
- public void saveClirSetting(int commandInterfaceCLIRMode) {
- }
-
@Override
public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
return null;
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index c19c28bc1f..072da68ed9 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -726,6 +726,8 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
return NetworkStats.UID_ALL;
}
+ // Initialize to UID_ALL so at least it can be counted to overall data usage if
+ // the dialer's package uid is not available.
int uid = NetworkStats.UID_ALL;
try {
uid = context.getPackageManager().getPackageUid(pkg, 0);
@@ -2549,7 +2551,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
&& targetAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN
&& targetAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
if (isHandoverFromWifi && imsCall.isVideoCall()) {
- if (mNotifyHandoverVideoFromWifiToLTE) {
+ if (mNotifyHandoverVideoFromWifiToLTE && mIsDataEnabled) {
log("onCallHandover :: notifying of WIFI to LTE handover.");
conn.onConnectionEvent(
TelephonyManager.EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE, null);
@@ -2558,7 +2560,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
if (!mIsDataEnabled && mIsViLteDataMetered) {
// Call was downgraded from WIFI to LTE and data is metered; downgrade the
// call now.
- downgradeVideoCall(ImsReasonInfo.CODE_DATA_DISABLED, conn);
+ downgradeVideoCall(ImsReasonInfo.CODE_WIFI_LOST, conn);
}
}
} else {
@@ -2999,6 +3001,17 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
// a separate entry if uid is different from the previous snapshot.
NetworkStats vtDataUsageUidSnapshot = new NetworkStats(currentTime, 1);
vtDataUsageUidSnapshot.combineAllValues(mVtDataUsageUidSnapshot);
+
+ // The dialer uid might not be initialized correctly during boot up due to telecom service
+ // not ready or its default dialer cache not ready. So we double check again here to see if
+ // default dialer uid is really not available.
+ if (mDefaultDialerUid.get() == NetworkStats.UID_ALL) {
+ final TelecomManager telecomManager =
+ (TelecomManager) mPhone.getContext().getSystemService(Context.TELECOM_SERVICE);
+ mDefaultDialerUid.set(
+ getPackageUid(mPhone.getContext(), telecomManager.getDefaultDialerPackage()));
+ }
+
// Since the modem only reports the total vt data usage rather than rx/tx separately,
// the only thing we can do here is splitting the usage into half rx and half tx.
vtDataUsageUidSnapshot.combineValues(new NetworkStats.Entry(
@@ -3507,8 +3520,9 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
// If the carrier supports downgrading to voice, then we can simply issue a
// downgrade to voice instead of terminating the call.
modifyVideoCall(imsCall, VideoProfile.STATE_AUDIO_ONLY);
- } else if (mSupportPauseVideo) {
- // The carrier supports video pause signalling, so pause the video.
+ } else if (mSupportPauseVideo && reasonCode != ImsReasonInfo.CODE_WIFI_LOST) {
+ // The carrier supports video pause signalling, so pause the video if we didn't just
+ // lose wifi; in that case just disconnect.
mShouldUpdateImsConfigOnDisconnect = true;
conn.pauseVideo(VideoPauseTracker.SOURCE_DATA_ENABLED);
} else {
diff --git a/src/java/com/android/internal/telephony/util/NotificationChannelController.java b/src/java/com/android/internal/telephony/util/NotificationChannelController.java
index 9967b05dc0..54d7d1abd8 100644
--- a/src/java/com/android/internal/telephony/util/NotificationChannelController.java
+++ b/src/java/com/android/internal/telephony/util/NotificationChannelController.java
@@ -58,21 +58,26 @@ public class NotificationChannelController {
alertChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build());
+ final NotificationChannel mobileDataStatusChannel = new NotificationChannel(
+ CHANNEL_ID_MOBILE_DATA_STATUS,
+ context.getText(R.string.notification_channel_mobile_data_status),
+ NotificationManager.IMPORTANCE_LOW);
+ // allow users to block notifications from system
+ mobileDataStatusChannel.setBlockableSystem(true);
+
context.getSystemService(NotificationManager.class)
.createNotificationChannels(Arrays.asList(
new NotificationChannel(CHANNEL_ID_CALL_FORWARD,
context.getText(R.string.notification_channel_call_forward),
NotificationManager.IMPORTANCE_LOW),
- new NotificationChannel(CHANNEL_ID_MOBILE_DATA_STATUS,
- context.getText(R.string.notification_channel_mobile_data_status),
- NotificationManager.IMPORTANCE_LOW),
new NotificationChannel(CHANNEL_ID_SMS,
context.getText(R.string.notification_channel_sms),
NotificationManager.IMPORTANCE_HIGH),
new NotificationChannel(CHANNEL_ID_WFC,
context.getText(R.string.notification_channel_wfc),
NotificationManager.IMPORTANCE_LOW),
- alertChannel));
+ alertChannel,
+ mobileDataStatusChannel));
// only for update
if (getChannel(CHANNEL_ID_VOICE_MAIL, context) != null) {
migrateVoicemailNotificationSettings(context);
diff --git a/tests/telephonytests/Android.mk b/tests/telephonytests/Android.mk
index fd2cbb2a57..b777fac90f 100644
--- a/tests/telephonytests/Android.mk
+++ b/tests/telephonytests/Android.mk
@@ -7,7 +7,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files)
#LOCAL_STATIC_JAVA_LIBRARIES := librilproto-java
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common ims-common services.core
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common ims-common services.core bouncycastle
LOCAL_STATIC_JAVA_LIBRARIES := guava \
frameworks-base-testutils \
mockito-target-minus-junit4 \
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
new file mode 100644
index 0000000000..4b99cbe58f
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2017 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.DownloadManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.HandlerThread;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.ImsiEncryptionInfo;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Pair;
+
+import com.android.org.bouncycastle.util.io.pem.PemReader;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.security.PublicKey;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import static android.preference.PreferenceManager.getDefaultSharedPreferences;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class CarrierKeyDownloadMgrTest extends TelephonyTest {
+
+ private static final String LOG_TAG = "CarrierKeyDownloadManager";
+
+ private CarrierKeyDownloadManager mCarrierKeyDM;
+ private CarrierActionAgentHandler mCarrierActionAgentHandler;
+
+ private String mURL = "http://www.google.com";
+
+ private static final String CERT = "-----BEGIN CERTIFICATE-----\r\nMIIFjzCCBHegAwIBAgIUPxj3SLif82Ky1RlUy8p2EWJCh8MwDQYJKoZIhvcNAQELBQAwgY0xCzAJBgNVBAYTAk5MMRIwEAYDVQQHEwlBbXN0ZXJkYW0xJTAjBgNVBAoTHFZlcml6b24gRW50ZXJwcmlzZSBTb2x1dGlvbnMxEzARBgNVBAsTCkN5YmVydHJ1c3QxLjAsBgNVBAMTJVZlcml6b24gUHVibGljIFN1cmVTZXJ2ZXIgQ0EgRzE0LVNIQTIwHhcNMTcwODE0MTc0MzM4WhcNMTkwODE0MTc0MzM4WjCBmTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFjAUBgNVBAcTDUJhc2tpbmcgUmlkZ2UxIjAgBgNVBAoTGVZlcml6b24gRGF0YSBTZXJ2aWNlcyBMTEMxHzAdBgNVBAsTFk5ldHdvcmsgU3lzdGVtIFN1cHBvcnQxGDAWBgNVBAMTD3ZpMWx2Lmltc3ZtLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALUQKWTHi4Hjpd1LQwJ87RXa0Rs3rVonvVevliqdUH5BikjhAzvIqwPSXeRQqkaRTFIyp0NKcNqGdjAaHRo43gdHeWSH331sS6CMZDg988gZznskzCqJJo6ii5FuLC8qe2YDsHxT+CefXev2rn6Bj1ei2X74uZsy5KlkBRZfFHtPdK6/EK5TpzrvcXfDyOK1rn8FTno1bQOTAhL39GPcLhdrXV7AN+lu+EBpdCqlTdcoDxsqavi/91MwUIVEzxJmycKloT6OWfU44r7+L5SYYgc88NTaGL/BvCFwHRIa1ZgYSGeAPes45792MGG7tfr/ttAGp9UEwTv2zWTxzWnRP/UCAwEAAaOCAdcwggHTMAwGA1UdEwEB/wQCMAAwTAYDVR0gBEUwQzBBBgkrBgEEAbE+ATIwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly9zZWN1cmUub21uaXJvb3QuY29tL3JlcG9zaXRvcnkwgakGCCsGAQUFBwEBBIGcMIGZMC0GCCsGAQUFBzABhiFodHRwOi8vdnBzc2cxNDIub2NzcC5vbW5pcm9vdC5jb20wMwYIKwYBBQUHMAKGJ2h0dHA6Ly9jYWNlcnQub21uaXJvb3QuY29tL3Zwc3NnMTQyLmNydDAzBggrBgEFBQcwAoYnaHR0cDovL2NhY2VydC5vbW5pcm9vdC5jb20vdnBzc2cxNDIuZGVyMBoGA1UdEQQTMBGCD3ZpMWx2Lmltc3ZtLmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB8GA1UdIwQYMBaAFOQtu5EBZSYftHo/oxUlpM6MRDM7MD4GA1UdHwQ3MDUwM6AxoC+GLWh0dHA6Ly92cHNzZzE0Mi5jcmwub21uaXJvb3QuY29tL3Zwc3NnMTQyLmNybDAdBgNVHQ4EFgQUv5SaSyNM/yXw1v0N9TNpjsFCaPcwDQYJKoZIhvcNAQELBQADggEBACNJusTULj1KyV4RwiskKfp4wI9Hsz3ESbZS/ijF9D57BQ0UwkELU9r6rEAhsYLUvMq4sDhDbYIdupgP4MBzFnjkKult7VQm5W3nCcuHgXYFAJ9Y1a4OZAo/4hrHj70W9TsQ1ioSMjUT4F8bDUYZI0kcyH8e/+2DaTsLUpHw3L+Keu8PsJVBLnvcKJjWrZD/Bgd6JuaTX2G84i0rY0GJuO9CxLNJa6n61Mz5cqLYIuwKgiVgTA2n71YITyFICOFPFX1vSx35AWvD6aVYblxtC8mpCdF2h4s1iyrpXeji2GCJLwsNVtTtNQ4zWX3Gnq683wzkYZeyOHUyftIgAQZ+HsY=\r\n-----END CERTIFICATE-----";
+
+
+ private String mJsonStr = "{ \"carrier-keys\": [ { \"certificate\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }, { \"certificate\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }]}";
+
+ private String mJsonStr1 = "{ \"carrier-keys\": [ { \"public-key\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }, { \"public-key\": \"" + CERT + "\", \"key-type\": \"WLAN\", \"key-identifier\": \"key1=value\", \"expiration-date\": 1502577746000 }]}";
+
+ private class CarrierActionAgentHandler extends HandlerThread {
+
+ private CarrierActionAgentHandler(String name) {
+ super(name);
+ }
+
+ @Override
+ public void onLooperPrepared() {
+ mCarrierKeyDM = new CarrierKeyDownloadManager(mPhone);
+ setReady(true);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ logd("CarrierActionAgentTest +Setup!");
+ MockitoAnnotations.initMocks(this);
+ super.setUp(getClass().getSimpleName());
+ mCarrierActionAgentHandler = new CarrierActionAgentHandler(getClass().getSimpleName());
+ mCarrierActionAgentHandler.start();
+ waitUntilReady();
+ logd("CarrierActionAgentTest -Setup!");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mCarrierActionAgentHandler.quit();
+ super.tearDown();
+ }
+
+ /* Checks if the expiration date is calculated correctly
+ * In this case the expiration date should be the next day.
+ */
+ @Test
+ @SmallTest
+ public void testExpirationDate1Day() {
+ java.security.PublicKey publicKey = null;
+ mCarrierKeyDM.mKeyAvailability = 3;
+ SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd");
+ Calendar cal = new GregorianCalendar();
+ cal.add(Calendar.DATE, 6);
+ Date date = cal.getTime();
+ Calendar expectedCal = new GregorianCalendar();
+ expectedCal.add(Calendar.DATE, 1);
+ String dateExpected = dt.format(expectedCal.getTime());
+ ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("mcc", "mnc", 1,
+ "keyIdentifier", publicKey, date);
+ when(mPhone.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(imsiEncryptionInfo);
+ Date expirationDate = new Date(mCarrierKeyDM.getExpirationDate());
+ assertTrue(dt.format(expirationDate).equals(dateExpected));
+ }
+
+ /**
+ * Checks if the expiration date is calculated correctly
+ * In this case the expiration date should be the expiration date of the key.
+ **/
+ @Test
+ @SmallTest
+ public void testExpirationDate7Day() {
+ java.security.PublicKey publicKey = null;
+ mCarrierKeyDM.mKeyAvailability = 3;
+ SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd");
+ Calendar cal = new GregorianCalendar();
+ cal.add(Calendar.DATE, 10);
+ Date date = cal.getTime();
+ Calendar expectedCal = new GregorianCalendar();
+ expectedCal.add(Calendar.DATE, 3);
+ String dateExpected = dt.format(expectedCal.getTime());
+ ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("mcc", "mnc", 1,
+ "keyIdentifier", publicKey, date);
+ when(mPhone.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(imsiEncryptionInfo);
+ Date expirationDate = new Date(mCarrierKeyDM.getExpirationDate());
+ assertTrue(dt.format(expirationDate).equals(dateExpected));
+ }
+
+ /**
+ * Checks if the json is parse correctly.
+ * Verify that setCarrierInfoForImsiEncryption is called with the right params
+ **/
+ @Test
+ @SmallTest
+ public void testParseJson() {
+ ByteArrayInputStream certBytes = new ByteArrayInputStream(CERT.getBytes());
+ Reader fRd = new BufferedReader(new InputStreamReader(certBytes));
+ PemReader reader = new PemReader(fRd);
+ Pair<PublicKey, Long> keyInfo = null;
+ try {
+ keyInfo = mCarrierKeyDM.getKeyInformation(reader.readPemObject().getContent());
+ } catch (Exception e) {
+ fail(LOG_TAG + "exception creating public key");
+ }
+ ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("310", "270", 2,
+ "key1=value", keyInfo.first, new Date(keyInfo.second));
+ String mccMnc = "310:270";
+ mCarrierKeyDM.parseJsonAndPersistKey(mJsonStr, mccMnc);
+ verify(mPhone, times(2)).setCarrierInfoForImsiEncryption(
+ (Matchers.refEq(imsiEncryptionInfo)));
+ }
+
+ /**
+ * Checks if the json is parse correctly.
+ * Same as testParseJason, except that the test looks for the "public-key" field.
+ **/
+ @Test
+ @SmallTest
+ public void testParseJsonPublicKey() {
+ ByteArrayInputStream certBytes = new ByteArrayInputStream(CERT.getBytes());
+ Reader fRd = new BufferedReader(new InputStreamReader(certBytes));
+ PemReader reader = new PemReader(fRd);
+ Pair<PublicKey, Long> keyInfo = null;
+ try {
+ keyInfo = mCarrierKeyDM.getKeyInformation(reader.readPemObject().getContent());
+ } catch (Exception e) {
+ fail(LOG_TAG + "exception creating public key");
+ }
+ ImsiEncryptionInfo imsiEncryptionInfo = new ImsiEncryptionInfo("310", "270", 2,
+ "key1=value", keyInfo.first, new Date(keyInfo.second));
+ String mccMnc = "310:270";
+ mCarrierKeyDM.parseJsonAndPersistKey(mJsonStr1, mccMnc);
+ verify(mPhone, times(2)).setCarrierInfoForImsiEncryption(
+ (Matchers.refEq(imsiEncryptionInfo)));
+ }
+
+ /**
+ * Checks if the json is parse correctly.
+ * Since the json is bad, we want to verify that savePublicKey is not called.
+ **/
+ @Test
+ @SmallTest
+ public void testParseBadJsonFail() {
+ String mccMnc = "310:290";
+ String badJsonStr = "{badJsonString}";
+ mCarrierKeyDM.parseJsonAndPersistKey(badJsonStr, mccMnc);
+ verify(mPhone, times(0)).setCarrierInfoForImsiEncryption(any());
+ }
+
+ /**
+ * Checks if the download is valid.
+ * returns true since the mnc/mcc is valid.
+ **/
+ @Test
+ @SmallTest
+ public void testIsValidDownload() {
+ String mccMnc = "310:260";
+ when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
+ assertTrue(mCarrierKeyDM.isValidDownload(mccMnc));
+ }
+
+ /**
+ * Checks if the download is valid.
+ * returns false since the mnc/mcc is in-valid.
+ **/
+ @Test
+ @SmallTest
+ public void testIsValidDownloadFail() {
+ String mccMnc = "310:290";
+ when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
+ assertFalse(mCarrierKeyDM.isValidDownload(mccMnc));
+ }
+
+ /**
+ * Tests if the key is enabled.
+ * tests for all bit-mask value.
+ **/
+ @Test
+ @SmallTest
+ public void testIsKeyEnabled() {
+ mCarrierKeyDM.mKeyAvailability = 3;
+ assertTrue(mCarrierKeyDM.isKeyEnabled(1));
+ assertTrue(mCarrierKeyDM.isKeyEnabled(2));
+ mCarrierKeyDM.mKeyAvailability = 2;
+ assertFalse(mCarrierKeyDM.isKeyEnabled(1));
+ assertTrue(mCarrierKeyDM.isKeyEnabled(2));
+ mCarrierKeyDM.mKeyAvailability = 1;
+ assertTrue(mCarrierKeyDM.isKeyEnabled(1));
+ assertFalse(mCarrierKeyDM.isKeyEnabled(2));
+ }
+
+ /**
+ * Tests sending the ACTION_DOWNLOAD_COMPLETE intent.
+ * Verify that the alarm will kick-off the next day.
+ **/
+ @Test
+ @SmallTest
+ public void testDownloadComplete() {
+ SharedPreferences.Editor editor = getDefaultSharedPreferences(mContext).edit();
+ String mccMnc = "310:260";
+ int slotId = mPhone.getPhoneId();
+ editor.putString("CARRIER_KEY_DM_MCC_MNC" + slotId, mccMnc);
+ editor.commit();
+
+ SimpleDateFormat dt = new SimpleDateFormat("yyyy-mm-dd");
+ Calendar expectedCal = new GregorianCalendar();
+ expectedCal.add(Calendar.DATE, 1);
+ String dateExpected = dt.format(expectedCal.getTime());
+
+ when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
+ Intent mIntent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+ mContext.sendBroadcast(mIntent);
+ Date expirationDate = new Date(mCarrierKeyDM.getExpirationDate());
+ assertTrue(dt.format(expirationDate).equals(dateExpected));
+ }
+
+ /**
+ * Test sending the ACTION_CARRIER_CONFIG_CHANGED intent.
+ * Verify that the right mnc/mcc gets stored in the preferences.
+ **/
+ @Test
+ @SmallTest
+ public void testCarrierConfigChanged() {
+ CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
+ mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ int slotId = mPhone.getPhoneId();
+ PersistableBundle bundle = carrierConfigManager.getConfigForSubId(slotId);
+ bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
+ bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
+
+ when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
+ Intent mIntent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mIntent.putExtra(PhoneConstants.PHONE_KEY, 0);
+ mContext.sendBroadcast(mIntent);
+ SharedPreferences preferences = getDefaultSharedPreferences(mContext);
+ String mccMnc = preferences.getString("CARRIER_KEY_DM_MCC_MNC" + slotId, null);
+ assertTrue(mccMnc.equals("310:260"));
+ }
+
+ /**
+ * Tests sending the INTENT_KEY_RENEWAL_ALARM_PREFIX intent.
+ * Verify that the right mnc/mcc gets stored in the preferences.
+ **/
+ @Test
+ @SmallTest
+ public void testAlarmRenewal() {
+ CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
+ mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ int slotId = mPhone.getPhoneId();
+ PersistableBundle bundle = carrierConfigManager.getConfigForSubId(slotId);
+ bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
+ bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
+
+ when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
+ Intent mIntent = new Intent("com.android.internal.telephony.carrier_key_download_alarm"
+ + slotId);
+ mContext.sendBroadcast(mIntent);
+ SharedPreferences preferences = getDefaultSharedPreferences(mContext);
+ String mccMnc = preferences.getString("CARRIER_KEY_DM_MCC_MNC" + slotId, null);
+ assertTrue(mccMnc.equals("310:260"));
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 7e8a4393fa..2afdcf97d7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.app.AppOpsManager;
+import android.app.DownloadManager;
import android.app.NotificationManager;
import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver;
@@ -240,6 +241,8 @@ public class ContextFixture implements TestFixture<Context> {
return mEuiccManager;
case Context.TELECOM_SERVICE:
return mTelecomManager;
+ case Context.DOWNLOAD_SERVICE:
+ return mDownloadManager;
case Context.DISPLAY_SERVICE:
case Context.POWER_SERVICE:
// PowerManager and DisplayManager are final classes so cannot be mocked,
@@ -496,6 +499,7 @@ public class ContextFixture implements TestFixture<Context> {
private final Resources mResources = mock(Resources.class);
private final PackageManager mPackageManager = mock(PackageManager.class);
private final TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
+ private final DownloadManager mDownloadManager = mock(DownloadManager.class);
private final AppOpsManager mAppOpsManager = mock(AppOpsManager.class);
private final NotificationManager mNotificationManager = mock(NotificationManager.class);
private final UserManager mUserManager = mock(UserManager.class);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index 260b23500b..5e3f9487c3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -26,6 +26,7 @@ import android.support.test.filters.FlakyTest;
import android.telephony.PhoneNumberUtils;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.SpannableStringBuilder;
+import android.text.style.TtsSpan;
import org.junit.Ignore;
import org.junit.Test;
@@ -751,4 +752,21 @@ public class PhoneNumberUtilsTest {
assertEquals("tim_123", PhoneNumberUtils.getUsernameFromUriNumber("tim_123@zzz.org"));
assertEquals("5103331245", PhoneNumberUtils.getUsernameFromUriNumber("5103331245"));
}
+
+ @SmallTest
+ @Test
+ public void testCreateTtsSpan() {
+ checkTtsNumber("650 555 1212", "650-555-1212");
+ checkTtsNumber("6505551212", "+1-650-555-1212");
+ checkTtsNumber("232", "232");
+ checkTtsNumber("*232", "*232");
+ checkTtsNumber("*232#", "*232#");
+ checkTtsNumber("*650 555 1212#", "*650-555-1212#");
+ }
+
+ private void checkTtsNumber(String expected, String sourceNumber) {
+ TtsSpan ttsSpan = PhoneNumberUtils.createTtsSpan(sourceNumber);
+ assertEquals(TtsSpan.TYPE_TELEPHONE, ttsSpan.getType());
+ assertEquals(expected, ttsSpan.getArgs().getString(TtsSpan.ARG_NUMBER_PARTS));
+ }
}
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 bb090147c5..02758ac397 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
@@ -47,8 +47,8 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Telephony;
import android.support.test.filters.FlakyTest;
+import android.support.test.filters.MediumTest;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.MediumTest;
import com.android.internal.telephony.FakeSmsContentProvider;
import com.android.internal.telephony.InboundSmsHandler;
@@ -781,4 +781,28 @@ public class GsmInboundSmsHandlerTest extends TelephonyTest {
verifySmsIntentBroadcasts(0);
}
+
+ @FlakyTest
+ @Ignore
+ @Test
+ @MediumTest
+ public void testWaitingStateTimeout() throws Exception {
+ transitionFromStartupToIdle();
+
+ // send new SMS to state machine and verify that triggers SMS_DELIVER_ACTION
+ mGsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS,
+ new AsyncResult(null, mSmsMessage, null));
+ waitForMs(100);
+
+ ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext, times(1)).sendBroadcast(
+ intentArgumentCaptor.capture());
+ assertEquals(Telephony.Sms.Intents.SMS_DELIVER_ACTION,
+ intentArgumentCaptor.getAllValues().get(0).getAction());
+ assertEquals("WaitingState", getCurrentState().getName());
+
+ waitForMs(InboundSmsHandler.STATE_TIMEOUT + 300);
+
+ assertEquals("IdleState", getCurrentState().getName());
+ }
}