Merge "Add string conversion support for RIL_UNSOL_EMERGENCY_NUMBER_LIST"
diff --git a/proto/src/telephony.proto b/proto/src/telephony.proto
index e9a564e..ec2acf4 100644
--- a/proto/src/telephony.proto
+++ b/proto/src/telephony.proto
@@ -331,6 +331,10 @@
RAT_IWLAN = 18;
RAT_LTE_CA = 19;
+
+ RAT_NR_NSA = 20;
+
+ RAT_NR_SA = 21;
}
// The information about IMS errors
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index f0c6262..7004ef2 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -754,7 +754,6 @@
@Override
public void registerForNetworkScanResult(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
mRilNetworkScanResultRegistrants.addUnique(h, what, obj);
}
@@ -983,8 +982,6 @@
@Override
public void registerForNattKeepaliveStatus(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
-
synchronized (mStateMonitor) {
mNattKeepaliveStatusRegistrants.addUnique(h, what, obj);
}
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 0393ffa..5eb0456 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -129,9 +129,15 @@
mPackageMonitor.register(
context, mHandler.getLooper(), UserHandle.ALL, false /* externalStorage */);
- mContext.registerReceiverAsUser(mUserUnlockedReceiver, UserHandle.SYSTEM,
+ try {
+ Context contextAsUser = mContext.createPackageContextAsUser(mContext.getPackageName(),
+ 0, UserHandle.SYSTEM);
+ contextAsUser.registerReceiver(mUserUnlockedReceiver,
new IntentFilter(Intent.ACTION_USER_UNLOCKED), null /* broadcastPermission */,
mHandler);
+ } catch (PackageManager.NameNotFoundException e) {
+ loge("Package name not found: " + e.getMessage());
+ }
}
// Create or dispose mBindings and mLastSimState objects.
@@ -424,6 +430,8 @@
Log.d(LOG_TAG, message);
}
+ private static void loge(String message) { Log.e(LOG_TAG, message); }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("CarrierServiceBindHelper:");
for (int i = 0; i < mBindings.size(); i++) {
diff --git a/src/java/com/android/internal/telephony/CellBroadcastHandler.java b/src/java/com/android/internal/telephony/CellBroadcastHandler.java
index 08be268..3d8cb0f 100644
--- a/src/java/com/android/internal/telephony/CellBroadcastHandler.java
+++ b/src/java/com/android/internal/telephony/CellBroadcastHandler.java
@@ -28,6 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.PermissionChecker;
+import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
@@ -41,14 +42,15 @@
import android.provider.Settings;
import android.provider.Telephony;
import android.provider.Telephony.CellBroadcasts;
+import android.telephony.CbGeoUtils;
+import android.telephony.CbGeoUtils.Geometry;
+import android.telephony.CbGeoUtils.LatLng;
import android.telephony.SmsCbMessage;
import android.telephony.SubscriptionManager;
import android.text.format.DateUtils;
import android.util.LocalLog;
import android.util.Log;
-import com.android.internal.telephony.CbGeoUtils.Geometry;
-import com.android.internal.telephony.CbGeoUtils.LatLng;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import java.io.FileDescriptor;
@@ -142,7 +144,7 @@
} else {
performGeoFencing(message, uri, message.getGeometries(), location);
}
- }, message.getMaximumWaitingTime());
+ }, message.getMaximumWaitingDuration());
} else {
if (DBG) {
log("Broadcast the message directly because no geo-fencing required, "
@@ -213,18 +215,18 @@
*/
protected void broadcastMessage(@NonNull SmsCbMessage message, @Nullable Uri messageUri) {
String receiverPermission;
- int appOp;
+ String appOp;
String msg;
Intent intent;
if (message.isEmergencyMessage()) {
msg = "Dispatching emergency SMS CB, SmsCbMessage is: " + message;
log(msg);
mLocalLog.log(msg);
- intent = new Intent(Telephony.Sms.Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION);
+ intent = new Intent(Telephony.Sms.Intents.ACTION_SMS_EMERGENCY_CB_RECEIVED);
//Emergency alerts need to be delivered with high priority
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
receiverPermission = Manifest.permission.RECEIVE_EMERGENCY_BROADCAST;
- appOp = AppOpsManager.OP_RECEIVE_EMERGECY_SMS;
+ appOp = AppOpsManager.OPSTR_RECEIVE_EMERGENCY_BROADCAST;
intent.putExtra(EXTRA_MESSAGE, message);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
@@ -237,9 +239,14 @@
if (additionalPackage != null) {
Intent additionalIntent = new Intent(intent);
additionalIntent.setPackage(additionalPackage);
- mContext.sendOrderedBroadcastAsUser(additionalIntent, UserHandle.ALL,
- receiverPermission, appOp, null, getHandler(), Activity.RESULT_OK,
- null, null);
+ try {
+ mContext.createPackageContextAsUser(
+ mContext.getPackageName(), 0, UserHandle.ALL)
+ .sendOrderedBroadcast(additionalIntent, receiverPermission, appOp,
+ null /* resultReceiver */, getHandler(), Activity.RESULT_OK,
+ null /* initialData */, null /* initialExtras */);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
}
}
@@ -249,8 +256,14 @@
for (String pkg : pkgs) {
// Explicitly send the intent to all the configured cell broadcast receivers.
intent.setPackage(pkg);
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, receiverPermission,
- appOp, mReceiver, getHandler(), Activity.RESULT_OK, null, null);
+ try {
+ mContext.createPackageContextAsUser(
+ mContext.getPackageName(), 0, UserHandle.ALL)
+ .sendOrderedBroadcast(intent, receiverPermission, appOp, mReceiver,
+ getHandler(), Activity.RESULT_OK, null /* initialData */,
+ null /* initialExtras */);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
}
} else {
msg = "Dispatching SMS CB, SmsCbMessage is: " + message;
@@ -261,14 +274,19 @@
// this intent.
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
receiverPermission = Manifest.permission.RECEIVE_SMS;
- appOp = AppOpsManager.OP_RECEIVE_SMS;
+ appOp = AppOpsManager.OPSTR_RECEIVE_SMS;
intent.putExtra(EXTRA_MESSAGE, message);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
mReceiverCount.incrementAndGet();
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, receiverPermission, appOp,
- mReceiver, getHandler(), Activity.RESULT_OK, null, null);
+ try {
+ mContext.createPackageContextAsUser(mContext.getPackageName(), 0, UserHandle.ALL)
+ .sendOrderedBroadcast(intent, receiverPermission, appOp, mReceiver,
+ getHandler(), Activity.RESULT_OK, null /* initialData */,
+ null /* initialExtras */);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
}
if (messageUri != null) {
@@ -397,8 +415,8 @@
}
private boolean hasPermission(String permission) {
- return PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(mContext, permission)
- == PERMISSION_GRANTED;
+ return PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(mContext,
+ permission) == PERMISSION_GRANTED;
}
private final LocationListener mLocationListener = new LocationListener() {
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index de4f7c0..0c60bc6 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -73,6 +73,7 @@
static final String CB_FACILITY_BA_MT = "AC";
static final String CB_FACILITY_BA_SIM = "SC";
static final String CB_FACILITY_BA_FD = "FD";
+ static final String CB_FACILITY_BIC_ACR = "AR";
// Used for various supp services apis
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index ede22e1..6cc9e63 100755
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -20,6 +20,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.DisconnectCause;
import android.telephony.Rlog;
import android.telephony.ServiceState;
@@ -94,7 +95,7 @@
public interface Listener {
public void onVideoStateChanged(int videoState);
public void onConnectionCapabilitiesChanged(int capability);
- public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat);
+ public void onCallRadioTechChanged(@RilRadioTechnology int vrat);
public void onVideoProviderChanged(
android.telecom.Connection.VideoProvider videoProvider);
public void onAudioQualityChanged(int audioQuality);
@@ -125,7 +126,7 @@
@Override
public void onConnectionCapabilitiesChanged(int capability) {}
@Override
- public void onCallRadioTechChanged(@ServiceState.RilRadioTechnology int vrat) {}
+ public void onCallRadioTechChanged(@RilRadioTechnology int vrat) {}
@Override
public void onVideoProviderChanged(
android.telecom.Connection.VideoProvider videoProvider) {}
@@ -227,7 +228,7 @@
*
* This is used to propagate the call radio technology to upper layer.
*/
- private @ServiceState.RilRadioTechnology int mCallRadioTech =
+ private @RilRadioTechnology int mCallRadioTech =
ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
private boolean mAudioModeIsVoip;
private int mAudioQuality;
@@ -902,7 +903,7 @@
* @return the RIL Voice Radio Technology used for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public @ServiceState.RilRadioTechnology int getCallRadioTech() {
+ public @RilRadioTechnology int getCallRadioTech() {
return mCallRadioTech;
}
@@ -980,7 +981,7 @@
* @param vrat the RIL voice radio technology for current connection,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ public void setCallRadioTech(@RilRadioTechnology int vrat) {
if (mCallRadioTech == vrat) {
return;
}
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 9cce7bc..d3a6cb5 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -24,7 +24,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.telephony.TelephonyRegistryManager;
+import android.telephony.TelephonyRegistryManager;
import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 1bbcd5e..6a22715 100755
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -30,6 +30,7 @@
import android.os.RegistrantList;
import android.os.SystemProperties;
import android.telecom.TelecomManager;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.DisconnectCause;
@@ -1654,7 +1655,7 @@
* @param vrat the RIL voice radio technology for CS calls,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public void dispatchCsCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ public void dispatchCsCallRadioTech(@RilRadioTechnology int vrat) {
if (mConnections == null) {
log("dispatchCsCallRadioTech: mConnections is null");
return;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 82bb78b..e8c988d 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -58,6 +58,7 @@
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.AccessNetworkConstants;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.ImsiEncryptionInfo;
@@ -947,27 +948,27 @@
/**
* ImsService reports "IN_SERVICE" for its voice registration state even if the device
* has lost the physical link to the tower. This helper method merges the IMS and modem
- * ServiceState, only overriding the voice registration state when we are registered to IMS over
- * IWLAN. In this case the voice registration state will always be "OUT_OF_SERVICE", so override
- * the voice registration state with the data registration state.
+ * ServiceState, only overriding the voice registration state when we are registered to IMS. In
+ * this case the voice registration state may be "OUT_OF_SERVICE", so override the voice
+ * registration state with the data registration state.
*/
private ServiceState mergeServiceStates(ServiceState baseSs, ServiceState imsSs) {
+ // No need to merge states if the baseSs is IN_SERVICE.
+ if (baseSs.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
+ return baseSs;
+ }
// "IN_SERVICE" in this case means IMS is registered.
if (imsSs.getVoiceRegState() != ServiceState.STATE_IN_SERVICE) {
return baseSs;
}
- if (imsSs.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
- ServiceState newSs = new ServiceState(baseSs);
- // Voice override for IWLAN. In this case, voice registration is OUT_OF_SERVICE, but
- // the data RAT is IWLAN, so use that as a basis for determining whether or not the
- // physical link is available.
- newSs.setVoiceRegState(baseSs.getDataRegState());
- newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
- return newSs;
- }
-
- return baseSs;
+ ServiceState newSs = new ServiceState(baseSs);
+ // Voice override for IMS case. In this case, voice registration is OUT_OF_SERVICE, but
+ // IMS is available, so use data registration state as a basis for determining
+ // whether or not the physical link is available.
+ newSs.setVoiceRegState(baseSs.getDataRegState());
+ newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
+ return newSs;
}
private boolean handleCallDeflectionIncallSupplementaryService(
@@ -1731,6 +1732,11 @@
}
@Override
+ public int getEmergencyNumberDbVersion() {
+ return getEmergencyNumberTracker().getEmergencyNumberDbVersion();
+ }
+
+ @Override
public void resetCarrierKeysForImsiEncryption() {
mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId);
}
@@ -3839,7 +3845,7 @@
* @return the RIL voice radio technology used for CS calls,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- public @ServiceState.RilRadioTechnology int getCsCallRadioTech() {
+ public @RilRadioTechnology int getCsCallRadioTech() {
int calcVrat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
if (mSST != null) {
calcVrat = getCsCallRadioTech(mSST.mSS.getVoiceRegState(),
@@ -3868,7 +3874,7 @@
* @return the RIL voice radio technology used for CS calls,
* see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
*/
- private @ServiceState.RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) {
+ private @RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) {
logd("getCsCallRadioTech, current vrs=" + vrs + ", vrat=" + vrat);
int calcVrat = vrat;
if (vrs != ServiceState.STATE_IN_SERVICE
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index c98d265..d2f256a 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -126,7 +126,7 @@
markMessagesAsRead((ArrayList<byte[]>) ar.result);
} else {
if (Rlog.isLoggable("SMS", Log.DEBUG)) {
- log("Cannot load Sms records");
+ loge("Cannot load Sms records");
}
mSms = null;
}
@@ -147,7 +147,7 @@
if (ar.exception == null) {
mSmsc = (String) ar.result;
} else {
- log("Cannot read SMSC");
+ loge("Cannot read SMSC");
mSmsc = null;
}
mLock.notifyAll();
@@ -194,7 +194,7 @@
//shouldn't really happen, as messages are marked as read, only
//after importing it from icc.
if (Rlog.isLoggable("SMS", Log.DEBUG)) {
- log("markMessagesAsRead - aborting, no icc card present.");
+ loge("markMessagesAsRead - aborting, no icc card present.");
}
return;
}
@@ -276,7 +276,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to update by index");
+ loge("interrupted while trying to update by index");
}
}
return mSuccess;
@@ -317,7 +317,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to update by index");
+ loge("interrupted while trying to update by index");
}
}
return mSuccess;
@@ -344,7 +344,7 @@
IccFileHandler fh = mPhone.getIccFileHandler();
if (fh == null) {
- Rlog.e(LOG_TAG, "Cannot load Sms records. No icc card?");
+ loge("Cannot load Sms records. No icc card?");
mSms = null;
return mSms;
}
@@ -355,7 +355,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to load from the Icc");
+ loge("interrupted while trying to load from the Icc");
}
}
return mSms;
@@ -610,7 +610,7 @@
try {
receivedIntent.send(result);
} catch (PendingIntent.CanceledException e) {
- Rlog.d(LOG_TAG, "receivedIntent cancelled.");
+ loge("receivedIntent cancelled.");
}
}
}
@@ -839,7 +839,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to read SMSC");
+ loge("interrupted while trying to read SMSC");
}
}
return mSmsc;
@@ -863,7 +863,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to write SMSC");
+ loge("interrupted while trying to write SMSC");
}
}
return mSuccess;
@@ -1119,7 +1119,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to set cell broadcast config");
+ loge("interrupted while trying to set cell broadcast config");
}
}
@@ -1139,7 +1139,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to set cell broadcast activation");
+ loge("interrupted while trying to set cell broadcast activation");
}
}
@@ -1160,7 +1160,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to set cdma broadcast config");
+ loge("interrupted while trying to set cdma broadcast config");
}
}
@@ -1180,7 +1180,7 @@
try {
mLock.wait();
} catch (InterruptedException e) {
- log("interrupted while trying to set cdma broadcast activation");
+ loge("interrupted while trying to set cdma broadcast activation");
}
}
@@ -1189,7 +1189,15 @@
@UnsupportedAppUsage
protected void log(String msg) {
- Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg);
+ Rlog.d(LOG_TAG, msg);
+ }
+
+ protected void loge(String msg) {
+ Rlog.e(LOG_TAG, msg);
+ }
+
+ protected void loge(String msg, Throwable e) {
+ Rlog.e(LOG_TAG, msg, e);
}
@UnsupportedAppUsage
@@ -1215,13 +1223,13 @@
}
final ContentResolver resolver = mContext.getContentResolver();
if (!isFailedOrDraft(resolver, messageUri)) {
- Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: not FAILED or DRAFT message");
+ loge("sendStoredText: not FAILED or DRAFT message");
returnUnspecifiedFailure(sentIntent);
return;
}
final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
if (textAndAddress == null) {
- Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredText: can not load text");
+ loge("sendStoredText: can not load text");
returnUnspecifiedFailure(sentIntent);
return;
}
@@ -1242,20 +1250,19 @@
}
final ContentResolver resolver = mContext.getContentResolver();
if (!isFailedOrDraft(resolver, messageUri)) {
- Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: "
- + "not FAILED or DRAFT message");
+ loge("sendStoredMultipartText: not FAILED or DRAFT message");
returnUnspecifiedFailure(sentIntents);
return;
}
final String[] textAndAddress = loadTextAndAddress(resolver, messageUri);
if (textAndAddress == null) {
- Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not load text");
+ loge("sendStoredMultipartText: can not load text");
returnUnspecifiedFailure(sentIntents);
return;
}
final ArrayList<String> parts = SmsManager.getDefault().divideMessage(textAndAddress[0]);
if (parts == null || parts.size() < 1) {
- Log.e(LOG_TAG, "[IccSmsInterfaceManager]sendStoredMultipartText: can not divide text");
+ loge("sendStoredMultipartText: can not divide text");
returnUnspecifiedFailure(sentIntents);
return;
}
@@ -1327,7 +1334,7 @@
|| type == Telephony.Sms.MESSAGE_TYPE_FAILED;
}
} catch (SQLiteException e) {
- Log.e(LOG_TAG, "[IccSmsInterfaceManager]isFailedOrDraft: query message type failed", e);
+ loge("isFailedOrDraft: query message type failed", e);
} finally {
if (cursor != null) {
cursor.close();
@@ -1358,7 +1365,7 @@
return new String[]{ cursor.getString(0), cursor.getString(1) };
}
} catch (SQLiteException e) {
- Log.e(LOG_TAG, "[IccSmsInterfaceManager]loadText: query message text failed", e);
+ loge("loadText: query message text failed", e);
} finally {
if (cursor != null) {
cursor.close();
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 3d66b60..934eddf 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -35,6 +35,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
@@ -1124,7 +1125,7 @@
* @param user user to deliver the intent to
*/
@UnsupportedAppUsage
- public void dispatchIntent(Intent intent, String permission, int appOp,
+ public void dispatchIntent(Intent intent, String permission, String appOp,
Bundle opts, BroadcastReceiver resultReceiver, UserHandle user, int subId) {
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
final String action = intent.getAction();
@@ -1174,13 +1175,23 @@
}
}
// Only pass in the resultReceiver when the USER_SYSTEM is processed.
- mContext.sendOrderedBroadcastAsUser(intent, targetUser, permission, appOp, opts,
- users[i] == UserHandle.USER_SYSTEM ? resultReceiver : null,
- getHandler(), Activity.RESULT_OK, null, null);
+ try {
+ mContext.createPackageContextAsUser(mContext.getPackageName(), 0, targetUser)
+ .sendOrderedBroadcast(intent, permission, appOp, opts,
+ users[i] == UserHandle.USER_SYSTEM ? resultReceiver : null,
+ getHandler(), Activity.RESULT_OK, null /* initialData */,
+ null /* initialExtras */);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
}
} else {
- mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts,
- resultReceiver, getHandler(), Activity.RESULT_OK, null, null);
+ try {
+ mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user)
+ .sendOrderedBroadcast(intent, permission, appOp, opts, resultReceiver,
+ getHandler(), Activity.RESULT_OK, null /* initialData */,
+ null /* initialExtras */);
+ } catch (PackageManager.NameNotFoundException ignored) {
+ }
}
}
@@ -1278,7 +1289,7 @@
Bundle options = handleSmsWhitelisting(intent.getComponent(), isClass0);
dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
- AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId);
+ AppOpsManager.OPSTR_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId);
}
/**
@@ -1465,7 +1476,7 @@
Bundle options = handleSmsWhitelisting(null, false /* bgActivityStartAllowed */);
dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
- AppOpsManager.OP_RECEIVE_SMS,
+ AppOpsManager.OPSTR_RECEIVE_SMS,
options, this, UserHandle.ALL, subId);
} else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) {
// Now dispatch the notification only intent
@@ -1488,7 +1499,7 @@
String mimeType = intent.getType();
dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
- WapPushOverSms.getAppOpsPermissionForIntent(mimeType), options, this,
+ WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options, this,
UserHandle.SYSTEM, subId);
} else {
// Now that the intents have been deleted we can clean up the PDU data.
diff --git a/src/java/com/android/internal/telephony/LocaleTracker.java b/src/java/com/android/internal/telephony/LocaleTracker.java
index b284799..95429ef 100755
--- a/src/java/com/android/internal/telephony/LocaleTracker.java
+++ b/src/java/com/android/internal/telephony/LocaleTracker.java
@@ -42,6 +42,7 @@
import android.util.LocalLog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.MccTable.MccMnc;
import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
@@ -282,23 +283,16 @@
private String getMccFromCellInfo() {
String selectedMcc = null;
if (mCellInfoList != null) {
- Map<String, Integer> countryCodeMap = new HashMap<>();
+ Map<String, Integer> mccMap = new HashMap<>();
int maxCount = 0;
for (CellInfo cellInfo : mCellInfoList) {
- String mcc = null;
- if (cellInfo instanceof CellInfoGsm) {
- mcc = ((CellInfoGsm) cellInfo).getCellIdentity().getMccString();
- } else if (cellInfo instanceof CellInfoLte) {
- mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMccString();
- } else if (cellInfo instanceof CellInfoWcdma) {
- mcc = ((CellInfoWcdma) cellInfo).getCellIdentity().getMccString();
- }
+ String mcc = getNetworkMcc(cellInfo);
if (mcc != null) {
int count = 1;
- if (countryCodeMap.containsKey(mcc)) {
- count = countryCodeMap.get(mcc) + 1;
+ if (mccMap.containsKey(mcc)) {
+ count = mccMap.get(mcc) + 1;
}
- countryCodeMap.put(mcc, count);
+ mccMap.put(mcc, count);
// This is unlikely, but if MCC from cell info looks different, we choose the
// MCC that occurs most.
if (count > maxCount) {
@@ -312,6 +306,67 @@
}
/**
+ * Get the most frequent MCC + MNC combination with the specified MCC using cell tower
+ * information. If no one combination is more frequent than any other an arbitrary MCC + MNC is
+ * returned with the matching MCC. The MNC value returned can be null if it is not provided by
+ * the cell tower information.
+ *
+ * @param mccToMatch the MCC to match
+ * @return a matching {@link MccMnc}. Null if the information is not available.
+ */
+ @Nullable
+ private MccMnc getMccMncFromCellInfo(String mccToMatch) {
+ MccMnc selectedMccMnc = null;
+ if (mCellInfoList != null) {
+ Map<MccMnc, Integer> mccMncMap = new HashMap<>();
+ int maxCount = 0;
+ for (CellInfo cellInfo : mCellInfoList) {
+ String mcc = getNetworkMcc(cellInfo);
+ if (Objects.equals(mcc, mccToMatch)) {
+ String mnc = getNetworkMnc(cellInfo);
+ MccMnc mccMnc = new MccMnc(mcc, mnc);
+ int count = 1;
+ if (mccMncMap.containsKey(mccMnc)) {
+ count = mccMncMap.get(mccMnc) + 1;
+ }
+ mccMncMap.put(mccMnc, count);
+ // This is unlikely, but if MCC from cell info looks different, we choose the
+ // MCC that occurs most.
+ if (count > maxCount) {
+ maxCount = count;
+ selectedMccMnc = mccMnc;
+ }
+ }
+ }
+ }
+ return selectedMccMnc;
+ }
+
+ private static String getNetworkMcc(CellInfo cellInfo) {
+ String mccString = null;
+ if (cellInfo instanceof CellInfoGsm) {
+ mccString = ((CellInfoGsm) cellInfo).getCellIdentity().getMccString();
+ } else if (cellInfo instanceof CellInfoLte) {
+ mccString = ((CellInfoLte) cellInfo).getCellIdentity().getMccString();
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ mccString = ((CellInfoWcdma) cellInfo).getCellIdentity().getMccString();
+ }
+ return mccString;
+ }
+
+ private static String getNetworkMnc(CellInfo cellInfo) {
+ String mccString = null;
+ if (cellInfo instanceof CellInfoGsm) {
+ mccString = ((CellInfoGsm) cellInfo).getCellIdentity().getMncString();
+ } else if (cellInfo instanceof CellInfoLte) {
+ mccString = ((CellInfoLte) cellInfo).getCellIdentity().getMncString();
+ } else if (cellInfo instanceof CellInfoWcdma) {
+ mccString = ((CellInfoWcdma) cellInfo).getCellIdentity().getMncString();
+ }
+ return mccString;
+ }
+
+ /**
* Called when SIM card state changed. Only when we absolutely know the SIM is absent, we get
* cell info from the network. Other SIM states like NOT_READY might be just a transitioning
* state.
@@ -454,41 +509,57 @@
*/
private synchronized void updateLocale() {
// If MCC is available from network service state, use it first.
- String mcc = null;
String countryIso = getCarrierCountry();
- boolean isBogusMcc = false;
+ String countryIsoDebugInfo = "getCarrierCountry()";
+
+ // For time zone detection we want the best geographical match we can get, which may differ
+ // from the countryIso.
+ String timeZoneCountryIso = null;
+ String timeZoneCountryIsoDebugInfo = null;
if (!TextUtils.isEmpty(mOperatorNumeric)) {
- try {
- mcc = mOperatorNumeric.substring(0, 3);
- countryIso = MccTable.countryCodeForMcc(mcc);
- if (!TextUtils.isEmpty(mcc) && TextUtils.isEmpty(countryIso)) {
- isBogusMcc = true;
- }
- } catch (StringIndexOutOfBoundsException ex) {
- loge("updateLocale: Can't get country from operator numeric. mcc = "
- + mcc + ". ex=" + ex);
+ MccMnc mccMnc = MccMnc.fromOperatorNumeric(mOperatorNumeric);
+ if (mccMnc != null) {
+ countryIso = MccTable.countryCodeForMcc(mccMnc.mcc);
+ countryIsoDebugInfo = "OperatorNumeric(" + mOperatorNumeric
+ + "): MccTable.countryCodeForMcc(\"" + mccMnc.mcc + "\")";
+ timeZoneCountryIso = MccTable.geoCountryCodeForMccMnc(mccMnc);
+ timeZoneCountryIsoDebugInfo =
+ "OperatorNumeric: MccTable.geoCountryCodeForMccMnc(" + mccMnc + ")";
+ } else {
+ loge("updateLocale: Can't get country from operator numeric. mOperatorNumeric = "
+ + mOperatorNumeric);
}
}
// If for any reason we can't get country from operator numeric, try to get it from cell
// info.
if (TextUtils.isEmpty(countryIso)) {
- mcc = getMccFromCellInfo();
+ String mcc = getMccFromCellInfo();
countryIso = MccTable.countryCodeForMcc(mcc);
+ countryIsoDebugInfo = "CellInfo: MccTable.countryCodeForMcc(\"" + mcc + "\")";
+
+ MccMnc mccMnc = getMccMncFromCellInfo(mcc);
+ if (mccMnc != null) {
+ timeZoneCountryIso = MccTable.geoCountryCodeForMccMnc(mccMnc);
+ timeZoneCountryIsoDebugInfo =
+ "CellInfo: MccTable.geoCountryCodeForMccMnc(" + mccMnc + ")";
+ }
}
if (mCountryOverride != null) {
countryIso = mCountryOverride;
- log("Override current country to " + mCountryOverride);
+ countryIsoDebugInfo = "mCountryOverride = \"" + mCountryOverride + "\"";
+ timeZoneCountryIso = countryIso;
+ timeZoneCountryIsoDebugInfo = countryIsoDebugInfo;
}
- log("updateLocale: mcc = " + mcc + ", country = " + countryIso
- + ", isBogusMcc = " + isBogusMcc);
- boolean countryChanged = false;
+ log("updateLocale: countryIso = " + countryIso
+ + ", countryIsoDebugInfo = " + countryIsoDebugInfo);
if (!Objects.equals(countryIso, mCurrentCountryIso)) {
- String msg = "updateLocale: Change the current country to \"" + countryIso
- + "\", mcc = " + mcc + ", mCellInfoList = " + mCellInfoList;
+ String msg = "updateLocale: Change the current country to \"" + countryIso + "\""
+ + ", countryIsoDebugInfo = " + countryIsoDebugInfo
+ + ", mCellInfoList = " + mCellInfoList;
log(msg);
mLocalLog.log(msg);
mCurrentCountryIso = countryIso;
@@ -500,15 +571,32 @@
intent.putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, countryIso);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
mPhone.getContext().sendBroadcast(intent);
-
- countryChanged = true;
}
- // For bogus mcc, the countryIso is always empty, it should be marked as available.
- if (TextUtils.isEmpty(countryIso) && !isBogusMcc) {
- mNitzStateMachine.handleNetworkCountryCodeUnavailable();
+ // Pass the geographical country information to the telephony time zone detection code.
+
+ boolean isTestMcc = false;
+ if (!TextUtils.isEmpty(mOperatorNumeric)) {
+ // For a test cell (MCC 001), the NitzStateMachine requires handleCountryDetected("") in
+ // order to pass compliance tests. http://b/142840879
+ if (mOperatorNumeric.startsWith("001")) {
+ isTestMcc = true;
+ timeZoneCountryIso = "";
+ timeZoneCountryIsoDebugInfo = "Test cell: " + mOperatorNumeric;
+ }
+ }
+ if (timeZoneCountryIso == null) {
+ // After this timeZoneCountryIso may still be null.
+ timeZoneCountryIso = countryIso;
+ timeZoneCountryIsoDebugInfo = "Defaulted: " + countryIsoDebugInfo;
+ }
+ log("updateLocale: timeZoneCountryIso = " + timeZoneCountryIso
+ + ", timeZoneCountryIsoDebugInfo = " + timeZoneCountryIsoDebugInfo);
+
+ if (TextUtils.isEmpty(timeZoneCountryIso) && !isTestMcc) {
+ mNitzStateMachine.handleCountryUnavailable();
} else {
- mNitzStateMachine.handleNetworkCountryCodeSet(countryChanged);
+ mNitzStateMachine.handleCountryDetected(timeZoneCountryIso);
}
}
diff --git a/src/java/com/android/internal/telephony/MccTable.java b/src/java/com/android/internal/telephony/MccTable.java
index 31b8d0a..d4c2e9a 100644
--- a/src/java/com/android/internal/telephony/MccTable.java
+++ b/src/java/com/android/internal/telephony/MccTable.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.content.Context;
@@ -27,9 +29,15 @@
import android.text.TextUtils;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.LocaleStore;
import com.android.internal.app.LocaleStore.LocaleInfo;
+import libcore.timezone.TelephonyLookup;
+import libcore.timezone.TelephonyNetwork;
+import libcore.timezone.TelephonyNetworkFinder;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -37,6 +45,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
/**
* Mobile Country Code
@@ -46,6 +55,9 @@
public final class MccTable {
static final String LOG_TAG = "MccTable";
+ @GuardedBy("MccTable.class")
+ private static TelephonyNetworkFinder sTelephonyNetworkFinder;
+
static ArrayList<MccEntry> sTable;
static class MccEntry implements Comparable<MccEntry> {
@@ -58,11 +70,11 @@
final String mIso;
final int mSmallestDigitsMnc;
- MccEntry(int mnc, String iso, int smallestDigitsMCC) {
+ MccEntry(int mcc, String iso, int smallestDigitsMCC) {
if (iso == null) {
throw new NullPointerException();
}
- mMcc = mnc;
+ mMcc = mcc;
mIso = iso;
mSmallestDigitsMnc = smallestDigitsMCC;
}
@@ -73,6 +85,77 @@
}
}
+ /**
+ * A combination of MCC and MNC. The MNC is optional and may be null.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static class MccMnc {
+ @NonNull
+ public final String mcc;
+
+ @Nullable
+ public final String mnc;
+
+ /**
+ * Splits the supplied String in two: the first three characters are treated as the MCC,
+ * the remaining characters are treated as the MNC.
+ */
+ @Nullable
+ public static MccMnc fromOperatorNumeric(@NonNull String operatorNumeric) {
+ Objects.requireNonNull(operatorNumeric);
+ String mcc;
+ try {
+ mcc = operatorNumeric.substring(0, 3);
+ } catch (StringIndexOutOfBoundsException e) {
+ return null;
+ }
+
+ String mnc;
+ try {
+ mnc = operatorNumeric.substring(3);
+ } catch (StringIndexOutOfBoundsException e) {
+ mnc = null;
+ }
+ return new MccMnc(mcc, mnc);
+ }
+
+ /**
+ * Creates an MccMnc using the supplied values.
+ */
+ public MccMnc(@NonNull String mcc, @Nullable String mnc) {
+ this.mcc = Objects.requireNonNull(mcc);
+ this.mnc = mnc;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ MccMnc mccMnc = (MccMnc) o;
+ return mcc.equals(mccMnc.mcc)
+ && Objects.equals(mnc, mccMnc.mnc);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mcc, mnc);
+ }
+
+ @Override
+ public String toString() {
+ return "MccMnc{"
+ + "mcc='" + mcc + '\''
+ + ", mnc='" + mnc + '\''
+ + '}';
+ }
+ }
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
publicAlternatives = "There is no alternative for {@code MccTable.entryForMcc}, "
+ "but it was included in hidden APIs due to a static analysis false positive "
@@ -91,11 +174,11 @@
}
/**
- * Given a GSM Mobile Country Code, returns
- * an ISO two-character country code if available.
- * Returns "" if unavailable.
+ * Given a GSM Mobile Country Code, returns a lower-case ISO 3166 alpha-2 country code if
+ * available. Returns empty string if unavailable.
*/
@UnsupportedAppUsage
+ @NonNull
public static String countryCodeForMcc(int mcc) {
MccEntry entry = entryForMcc(mcc);
@@ -107,11 +190,11 @@
}
/**
- * Given a GSM Mobile Country Code, returns
- * an ISO two-character country code if available.
- * Returns empty string if unavailable.
+ * Given a GSM Mobile Country Code, returns a lower-case ISO 3166 alpha-2 country code if
+ * available. Returns empty string if unavailable.
*/
- public static String countryCodeForMcc(String mcc) {
+ @NonNull
+ public static String countryCodeForMcc(@NonNull String mcc) {
try {
return countryCodeForMcc(Integer.parseInt(mcc));
} catch (NumberFormatException ex) {
@@ -120,6 +203,51 @@
}
/**
+ * Given a combination of MCC and MNC, returns a lower case ISO 3166 alpha-2 country code for
+ * the device's geographical location.
+ *
+ * <p>This can give a better geographical result than {@link #countryCodeForMcc(String)}
+ * (which provides the official "which country is the MCC assigned to?" answer) for cases when
+ * MNC is also available: Sometimes an MCC can be used by multiple countries and the MNC can
+ * help distinguish, or the MCC assigned to a country isn't used for geopolitical reasons.
+ * When the geographical country is needed (e.g. time zone detection) this version can provide
+ * more pragmatic results than the official MCC-only answer. This method falls back to calling
+ * {@link #countryCodeForMcc(int)} if no special MCC+MNC cases are found.
+ * Returns empty string if no code can be determined.
+ */
+ @NonNull
+ public static String geoCountryCodeForMccMnc(@NonNull MccMnc mccMnc) {
+ String countryCode = null;
+ if (mccMnc.mnc != null) {
+ countryCode = countryCodeForMccMncNoFallback(mccMnc);
+ }
+ if (TextUtils.isEmpty(countryCode)) {
+ // Try the MCC-only fallback.
+ countryCode = MccTable.countryCodeForMcc(mccMnc.mcc);
+ }
+ return countryCode;
+ }
+
+ @Nullable
+ private static String countryCodeForMccMncNoFallback(MccMnc mccMnc) {
+ synchronized (MccTable.class) {
+ if (sTelephonyNetworkFinder == null) {
+ sTelephonyNetworkFinder = TelephonyLookup.getInstance().getTelephonyNetworkFinder();
+ }
+ }
+ if (sTelephonyNetworkFinder == null) {
+ // This should not happen under normal circumstances, only when the data is missing.
+ return null;
+ }
+ TelephonyNetwork network =
+ sTelephonyNetworkFinder.findNetworkByMccMnc(mccMnc.mcc, mccMnc.mnc);
+ if (network == null) {
+ return null;
+ }
+ return network.getCountryIsoCode();
+ }
+
+ /**
* Given a GSM Mobile Country Code, returns
* an ISO 2-3 character language code if available.
* Returns null if unavailable.
diff --git a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
index 1b28be4..bd90be6 100644
--- a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
+++ b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.IBinder;
@@ -99,8 +100,14 @@
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- phone.getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- intentFilter, null, null);
+ try {
+ Context contextAsUser = phone.getContext().createPackageContextAsUser(
+ phone.getContext().getPackageName(), 0, UserHandle.ALL);
+ contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter,
+ null /* broadcastPermission */, null);
+ } catch (PackageManager.NameNotFoundException e) {
+ loge("Package name not found: " + e.getMessage());
+ }
PhoneConfigurationManager.registerForMultiSimConfigChange(
this, EVENT_BIND_NETWORK_SERVICE, null);
diff --git a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
index c848358..895170d 100644
--- a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
+++ b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
@@ -66,10 +66,12 @@
private static final int EVENT_STOP_NETWORK_SCAN_DONE = 5;
private static final int CMD_INTERRUPT_NETWORK_SCAN = 6;
private static final int EVENT_INTERRUPT_NETWORK_SCAN_DONE = 7;
+ private static final int EVENT_MODEM_RESET = 8;
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
+ Log.d(TAG, "Received Event :" + msg.what);
switch (msg.what) {
case CMD_START_NETWORK_SCAN:
mScheduler.doStartScan((NetworkScanRequestInfo) msg.obj);
@@ -98,6 +100,14 @@
case EVENT_INTERRUPT_NETWORK_SCAN_DONE:
mScheduler.interruptScanDone((AsyncResult) msg.obj);
break;
+
+ case EVENT_MODEM_RESET:
+ AsyncResult ar = (AsyncResult) msg.obj;
+ mScheduler.deleteScanAndMayNotify(
+ (NetworkScanRequestInfo) ar.userObj,
+ NetworkScan.ERROR_MODEM_ERROR,
+ true);
+ break;
}
}
};
@@ -551,6 +561,7 @@
mLiveRequestInfo = nsri;
nsri.mPhone.startNetworkScan(nsri.getRequest(),
mHandler.obtainMessage(EVENT_START_NETWORK_SCAN_DONE, nsri));
+ nsri.mPhone.mCi.registerForModemReset(mHandler, EVENT_MODEM_RESET, nsri);
return true;
}
return false;
@@ -570,6 +581,7 @@
null);
}
}
+ mLiveRequestInfo.mPhone.mCi.unregisterForModemReset(mHandler);
mLiveRequestInfo = null;
if (mPendingRequestInfo != null) {
startNewScan(mPendingRequestInfo);
diff --git a/src/java/com/android/internal/telephony/NitzStateMachine.java b/src/java/com/android/internal/telephony/NitzStateMachine.java
index 9e98cae..38c8c56 100644
--- a/src/java/com/android/internal/telephony/NitzStateMachine.java
+++ b/src/java/com/android/internal/telephony/NitzStateMachine.java
@@ -17,13 +17,11 @@
package com.android.internal.telephony;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
-import android.telephony.TelephonyManager;
import android.util.TimestampedValue;
import com.android.internal.util.IndentingPrintWriter;
@@ -40,13 +38,12 @@
public interface NitzStateMachine {
/**
- * Called when the network country is set on the Phone. Although set, the network country code
- * may be invalid.
+ * Called when the country suitable for time zone detection is detected.
*
- * @param countryChanged true when the country code is known to have changed, false if it
- * probably hasn't
+ * @param countryIsoCode the countryIsoCode to use for time zone detection, may be "" for test
+ * cells only, otherwise {@link #handleCountryUnavailable()} should be called
*/
- void handleNetworkCountryCodeSet(boolean countryChanged);
+ void handleCountryDetected(@NonNull String countryIsoCode);
/**
* Informs the {@link NitzStateMachine} that the network has become available.
@@ -54,15 +51,16 @@
void handleNetworkAvailable();
/**
- * Informs the {@link NitzStateMachine} that the network has become unavailable.
+ * Informs the {@link NitzStateMachine} that the network has become unavailable. Any network
+ * state, i.e. NITZ, should be cleared.
*/
void handleNetworkUnavailable();
/**
- * Informs the {@link NitzStateMachine} that the country code from network has become
- * unavailable.
+ * Informs the {@link NitzStateMachine} that any previously detected country supplied via
+ * {@link #handleCountryDetected(String)} is no longer valid.
*/
- void handleNetworkCountryCodeUnavailable();
+ void handleCountryUnavailable();
/**
* Handle a new NITZ signal being received.
@@ -108,8 +106,6 @@
*/
boolean getIgnoreNitz();
- @Nullable String getNetworkCountryIsoForPhone();
-
/**
* Returns the same value as {@link SystemClock#elapsedRealtime()}.
*/
@@ -133,16 +129,10 @@
private static final int NITZ_UPDATE_DIFF_DEFAULT = 2000;
private final int mNitzUpdateDiff;
- private final Phone mPhone;
- private final TelephonyManager mTelephonyManager;
private final ContentResolver mCr;
public DeviceStateImpl(Phone phone) {
- mPhone = phone;
-
Context context = phone.getContext();
- mTelephonyManager =
- (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mCr = context.getContentResolver();
mNitzUpdateSpacing =
SystemProperties.getInt("ro.nitz_update_spacing", NITZ_UPDATE_SPACING_DEFAULT);
@@ -168,12 +158,6 @@
}
@Override
- @Nullable
- public String getNetworkCountryIsoForPhone() {
- return mTelephonyManager.getNetworkCountryIso(mPhone.getPhoneId());
- }
-
- @Override
public long elapsedRealtime() {
return SystemClock.elapsedRealtime();
}
diff --git a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
index ffcb33d..7760394 100644
--- a/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/NitzStateMachineImpl.java
@@ -56,13 +56,11 @@
private TimestampedValue<NitzData> mLatestNitzSignal;
/**
- * Records whether the device should have a country code available via
- * {@link DeviceState#getNetworkCountryIsoForPhone()}. Before this an NITZ signal
- * received is (almost always) not enough to determine time zone. On test networks the country
- * code should be available but can still be an empty string but this flag indicates that the
- * information available is unlikely to improve.
+ * Records the country to use for time zone detection. It can be a valid ISO 3166 alpha-2 code
+ * (lower case), empty (test network) or null (no country detected). A country code is required
+ * to determine time zone except when on a test network.
*/
- private boolean mGotCountryCode = false;
+ private String mCountryIsoCode;
/**
* The last time zone ID that has been determined. It may not have been set as the device time
@@ -82,7 +80,7 @@
/**
* Boolean is {@code true} if NITZ has been used to determine a time zone (which may not
* ultimately have been used due to user settings). Cleared by {@link
- * #handleNetworkAvailable()}, {@link #handleNetworkCountryCodeUnavailable()},
+ * #handleNetworkAvailable()}, {@link #handleCountryUnavailable()},
* {@link #handleNetworkUnavailable()}, and {@link #handleAirplaneModeChanged(boolean)}. The
* flag can be used when historic NITZ data may no longer be valid. {@code false} indicates it
* is reasonable to try to set the time zone using less reliable algorithms than NITZ-based
@@ -132,16 +130,16 @@
}
@Override
- public void handleNetworkCountryCodeSet(boolean countryChanged) {
- boolean hadCountryCode = mGotCountryCode;
- mGotCountryCode = true;
+ public void handleCountryDetected(String countryIsoCode) {
+ String oldCountryIsoCode = mCountryIsoCode;
+ mCountryIsoCode = Objects.requireNonNull(countryIsoCode);
- String isoCountryCode = mDeviceState.getNetworkCountryIsoForPhone();
- if (!TextUtils.isEmpty(isoCountryCode) && !mNitzTimeZoneDetectionSuccessful) {
- updateTimeZoneFromNetworkCountryCode(isoCountryCode);
+ if (!TextUtils.isEmpty(countryIsoCode) && !mNitzTimeZoneDetectionSuccessful) {
+ updateTimeZoneFromNetworkCountryCode(countryIsoCode);
}
- if (mLatestNitzSignal != null && (countryChanged || !hadCountryCode)) {
+ boolean countryChanged = Objects.equals(oldCountryIsoCode, countryIsoCode);
+ if (mLatestNitzSignal != null && (countryChanged || oldCountryIsoCode == null)) {
updateTimeZoneFromCountryAndNitz();
}
}
@@ -150,7 +148,7 @@
// This method must only be called after mLatestNitzSignal has been set to a non-null
// value.
TimestampedValue<NitzData> nitzSignal = Objects.requireNonNull(mLatestNitzSignal);
- String isoCountryCode = mDeviceState.getNetworkCountryIsoForPhone();
+ String isoCountryCode = mCountryIsoCode;
// TimeZone.getDefault() returns a default zone (GMT) even when time zone have never
// been set which makes it difficult to tell if it's what the user / time zone detection
@@ -172,7 +170,7 @@
String zoneId;
if (nitzData.getEmulatorHostTimeZone() != null) {
zoneId = nitzData.getEmulatorHostTimeZone().getID();
- } else if (!mGotCountryCode) {
+ } else if (isoCountryCode == null) {
// We don't have a country code so we won't try to look up the time zone.
zoneId = null;
} else if (TextUtils.isEmpty(isoCountryCode)) {
@@ -269,6 +267,8 @@
logMsg += " [Not setting device time zone (zoneId == null)]";
Rlog.d(LOG_TAG, logMsg);
}
+ mSavedTimeZoneId = null;
+ mNitzTimeZoneDetectionSuccessful = false;
}
} catch (RuntimeException ex) {
Rlog.e(LOG_TAG, "updateTimeZoneFromCountryAndNitz: Processing NITZ data"
@@ -321,36 +321,44 @@
mSavedNitzTime = null;
mTimeLog.log("handleNetworkUnavailable: NITZ state cleared.");
+ TimestampedValue<NitzData> oldNitzSignal = mLatestNitzSignal;
mLatestNitzSignal = null;
mNitzTimeZoneDetectionSuccessful = false;
mSavedTimeZoneId = null;
mTimeZoneLog.log("handleNetworkUnavailable: NITZ state cleared.");
- // mSavedTimeZoneId has been cleared but it might be sufficient to detect the time zone
- // using only the country information that is left.
- if (mGotCountryCode) {
- String isoCountryCode = mDeviceState.getNetworkCountryIsoForPhone();
- if (!TextUtils.isEmpty(isoCountryCode)) {
- updateTimeZoneFromNetworkCountryCode(isoCountryCode);
- }
+ // Avoid doing work unnecessarily: if the mLatestNitzSignal was already null we have nothing
+ // to do as it will have been done last time the mLatestNitzSignal was cleared.
+ if (oldNitzSignal == null) {
+ return;
}
+
+ // mSavedTimeZoneId has been cleared but using only the country information that is left
+ // might be sufficient to detect the time zone.
+ String isoCountryCode = mCountryIsoCode;
+ // We don't need to do country-based time zone detection if the isoCountryCode is null
+ // (unknown) or empty (test cell). TextUtils.isEmpty() does both checks in one.
+ if (!TextUtils.isEmpty(isoCountryCode)) {
+ updateTimeZoneFromNetworkCountryCode(isoCountryCode);
+ }
+ sendEmptyTimeSuggestion("handleNetworkUnavailable");
}
@Override
- public void handleNetworkCountryCodeUnavailable() {
+ public void handleCountryUnavailable() {
if (DBG) {
Rlog.d(LOG_TAG, "handleNetworkCountryCodeUnavailable");
}
mSavedTimeZoneId = null;
- mGotCountryCode = false;
+ mCountryIsoCode = null;
mNitzTimeZoneDetectionSuccessful = false;
}
@Override
public void handleNitzReceived(TimestampedValue<NitzData> nitzSignal) {
// Always store the latest NITZ signal received.
- mLatestNitzSignal = nitzSignal;
+ mLatestNitzSignal = Objects.requireNonNull(nitzSignal);
updateTimeZoneFromCountryAndNitz();
updateTimeFromNitz();
@@ -377,15 +385,30 @@
mSavedNitzTime = null;
mTimeLog.log("handleAirplaneModeChanged(" + on + "): Time state cleared.");
- mGotCountryCode = false;
+ mCountryIsoCode = null;
+
+ TimestampedValue<NitzData> oldNitzSignal = mLatestNitzSignal;
mLatestNitzSignal = null;
mNitzTimeZoneDetectionSuccessful = false;
mSavedTimeZoneId = null;
+
+ if (oldNitzSignal == null) {
+ // No work to do - terminate early.
+ return;
+ }
+
mTimeZoneLog.log("handleAirplaneModeChanged(" + on + "): Time zone state cleared.");
+ sendEmptyTimeSuggestion("handleAirplaneModeChanged(" + on + ")");
+ }
+
+ private void sendEmptyTimeSuggestion(String reason) {
+ PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhone.getPhoneId());
+ timeSuggestion.addDebugInfo("Empty suggestion, reason=" + reason);
+ mTimeServiceHelper.suggestDeviceTime(timeSuggestion);
}
private void updateTimeFromNitz() {
- TimestampedValue<NitzData> nitzSignal = mLatestNitzSignal;
+ TimestampedValue<NitzData> nitzSignal = Objects.requireNonNull(mLatestNitzSignal);
try {
boolean ignoreNitz = mDeviceState.getIgnoreNitz();
if (ignoreNitz) {
@@ -461,8 +484,8 @@
Rlog.d(LOG_TAG, logMsg);
}
mTimeLog.log(logMsg);
- PhoneTimeSuggestion phoneTimeSuggestion =
- new PhoneTimeSuggestion(mPhone.getPhoneId(), newNitzTime);
+ PhoneTimeSuggestion phoneTimeSuggestion = new PhoneTimeSuggestion(mPhone.getPhoneId());
+ phoneTimeSuggestion.setUtcTime(newNitzTime);
phoneTimeSuggestion.addDebugInfo(logMsg);
mTimeServiceHelper.suggestDeviceTime(phoneTimeSuggestion);
@@ -521,7 +544,7 @@
// Time Zone Detection State
pw.println(" mLatestNitzSignal=" + mLatestNitzSignal);
- pw.println(" mGotCountryCode=" + mGotCountryCode);
+ pw.println(" mCountryIsoCode=" + mCountryIsoCode);
pw.println(" mSavedTimeZoneId=" + mSavedTimeZoneId);
pw.println(" mNitzTimeZoneDetectionSuccessful=" + mNitzTimeZoneDetectionSuccessful);
@@ -578,6 +601,7 @@
+ " iso=" + iso
+ " lookupResult=" + lookupResult);
}
+ mSavedTimeZoneId = null;
}
}
@@ -590,4 +614,9 @@
public NitzData getCachedNitzData() {
return mLatestNitzSignal != null ? mLatestNitzSignal.getValue() : null;
}
+
+ // VisibleForTesting
+ public String getSavedTimeZoneId() {
+ return mSavedTimeZoneId;
+ }
}
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index fd22e77..efa3954 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -2362,6 +2362,15 @@
mCi.nvResetConfig(3 /* factory NV reset */, response);
}
+ /**
+ * Perform modem configuration erase. Used for network reset
+ *
+ * @param response Callback message.
+ */
+ public void eraseModemConfig(Message response) {
+ mCi.nvResetConfig(2 /* erase NV */, response);
+ }
+
public void notifyDataActivity() {
mNotifier.notifyDataActivity(this);
}
@@ -3421,6 +3430,10 @@
return TelephonyManager.UNKNOWN_CARRIER_ID_LIST_VERSION;
}
+ public int getEmergencyNumberDbVersion() {
+ return TelephonyManager.INVALID_EMERGENCY_NUMBER_DB_VERSION;
+ }
+
public void resolveSubscriptionCarrierId(String simState) {
}
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index df73ef8..2ad6056 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -30,6 +30,7 @@
import android.os.storage.StorageManager;
import android.telephony.PhoneCapability;
import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -130,19 +131,6 @@
}
/**
- * Whether the phoneId has a corresponding active slot / logical modem. If a DSDS capable
- * device is in single SIM mode, phoneId=1 is valid but not active.
- *
- * TODO: b/139642279 combine with SubscriptionManager#isValidPhoneId when phone objects
- * are dynamically allocated instead of always based on getMaxPhoneCount.
- * @hide
- */
- public static boolean isPhoneActive(int phoneId) {
- // Currently it simply depends on getPhoneCount. In future it can be generalized.
- return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount();
- }
-
- /**
* Handler class to handle callbacks
*/
private final class ConfigManagerHandler extends Handler {
@@ -366,11 +354,12 @@
pm.reboot("Multi-SIM config changed.");
} else {
log("onMultiSimConfigChanged: Rebooting is not required.");
+ mMi.notifyPhoneFactoryOnMultiSimConfigChanged(mContext, numOfActiveModems);
broadcastMultiSimConfigChange(numOfActiveModems);
// Register to RIL service if needed.
for (int i = 0; i < mPhones.length; i++) {
Phone phone = mPhones[i];
- phone.mCi.onSlotActiveStatusChange(isPhoneActive(i));
+ phone.mCi.onSlotActiveStatusChange(SubscriptionManager.isValidPhoneId(i));
}
}
}
@@ -426,6 +415,9 @@
*/
@VisibleForTesting
public static class MockableInterface {
+ /**
+ * Wrapper function to decide whether reboot is required for modem config change.
+ */
@VisibleForTesting
public boolean isRebootRequiredForModemConfigChange() {
String rebootRequired = SystemProperties.get(
@@ -434,6 +426,9 @@
return !rebootRequired.equals("false");
}
+ /**
+ * Wrapper function to call setMultiSimProperties.
+ */
@VisibleForTesting
public void setMultiSimProperties(int numOfActiveModems) {
String multiSimConfig;
@@ -451,6 +446,15 @@
log("setMultiSimProperties to " + multiSimConfig);
SystemProperties.set(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG, multiSimConfig);
}
+
+ /**
+ * Wrapper function to call PhoneFactory.onMultiSimConfigChanged.
+ */
+ @VisibleForTesting
+ public void notifyPhoneFactoryOnMultiSimConfigChanged(
+ Context context, int numOfActiveModems) {
+ PhoneFactory.onMultiSimConfigChanged(context, numOfActiveModems);
+ }
}
private static void log(String s) {
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index b92c68b..a5b6437 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -16,6 +16,11 @@
package com.android.internal.telephony;
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA_LTE;
+
+import static java.util.Arrays.copyOf;
+
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -24,7 +29,6 @@
import android.content.pm.PackageManager;
import android.net.LocalServerSocket;
import android.os.Looper;
-import android.os.ServiceManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -87,7 +91,6 @@
static private Context sContext;
static private PhoneConfigurationManager sPhoneConfigurationManager;
static private PhoneSwitcher sPhoneSwitcher;
- static private SubscriptionMonitor sSubscriptionMonitor;
static private TelephonyNetworkFactory[] sTelephonyNetworkFactories;
static private ImsResolver sImsResolver;
static private NotificationChannelController sNotificationChannelController;
@@ -146,7 +149,7 @@
/* In case of multi SIM mode two instances of Phone, RIL are created,
where as in single SIM mode only instance. isMultiSimEnabled() function checks
whether it is single SIM or multi SIM mode */
- int numPhones = TelephonyManager.getDefault().getSupportedModemCount();
+ int numPhones = TelephonyManager.getDefault().getActiveModemCount();
int[] networkModes = new int[numPhones];
sPhones = new Phone[numPhones];
@@ -165,7 +168,7 @@
// Instantiate UiccController so that all other classes can just
// call getInstance()
- sUiccController = UiccController.make(context, sCommandsInterfaces);
+ sUiccController = UiccController.make(context);
Rlog.i(LOG_TAG, "Creating SubscriptionController");
SubscriptionController sc = SubscriptionController.init(context);
@@ -178,28 +181,13 @@
}
for (int i = 0; i < numPhones; i++) {
- Phone phone = null;
- int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
- if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
- phone = new GsmCdmaPhone(context,
- sCommandsInterfaces[i], sPhoneNotifier, i,
- PhoneConstants.PHONE_TYPE_GSM,
- TelephonyComponentFactory.getInstance());
- } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
- phone = new GsmCdmaPhone(context,
- sCommandsInterfaces[i], sPhoneNotifier, i,
- PhoneConstants.PHONE_TYPE_CDMA_LTE,
- TelephonyComponentFactory.getInstance());
- }
- Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);
-
- sPhones[i] = phone;
+ sPhones[i] = createPhone(context, i);
}
// Set the default phone in base class.
// FIXME: This is a first best guess at what the defaults will be. It
// FIXME: needs to be done in a more controlled manner in the future.
- sPhone = sPhones[0];
+ if (numPhones > 0) sPhone = sPhones[0];
// Ensure that we have a default SMS app. Requesting the app with
// updateIfNeeded set to true is enough to configure a default SMS app.
@@ -219,7 +207,6 @@
Rlog.i(LOG_TAG, "Creating SubInfoRecordUpdater ");
sSubInfoRecordUpdater = new SubscriptionInfoUpdater(
BackgroundThread.get().getLooper(), context, sCommandsInterfaces);
- sc.updatePhonesAvailability(sPhones);
// Only bring up IMS if the device supports having an IMS stack.
if (context.getPackageManager().hasSystemFeature(
@@ -247,11 +234,6 @@
Rlog.i(LOG_TAG, "IMS is not supported on this device, skipping ImsResolver.");
}
- ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(
- ServiceManager.getService("telephony.registry"));
-
- sSubscriptionMonitor = new SubscriptionMonitor(tr, sContext, sc, numPhones);
-
sPhoneConfigurationManager = PhoneConfigurationManager.init(sContext);
sCellularNetworkValidator = CellularNetworkValidator.make(sContext);
@@ -259,11 +241,9 @@
int maxActivePhones = sPhoneConfigurationManager
.getNumberOfModemsWithSimultaneousDataConnections();
- sPhoneSwitcher = PhoneSwitcher.make(maxActivePhones, numPhones,
- sContext, sc, Looper.myLooper(), tr, sCommandsInterfaces,
- sPhones);
+ sPhoneSwitcher = PhoneSwitcher.make(maxActivePhones, sContext, Looper.myLooper());
- sProxyController = ProxyController.getInstance(context, sPhones, sPhoneSwitcher);
+ sProxyController = ProxyController.getInstance(context);
sIntentBroadcaster = IntentBroadcaster.getInstance(context);
@@ -271,12 +251,59 @@
for (int i = 0; i < numPhones; i++) {
sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
- sSubscriptionMonitor, Looper.myLooper(), sPhones[i]);
+ Looper.myLooper(), sPhones[i]);
}
}
}
}
+ /**
+ * Upon single SIM to dual SIM switch or vice versa, we dynamically allocate or de-allocate
+ * Phone and CommandInterface objects.
+ * @param context
+ * @param activeModemCount
+ */
+ public static void onMultiSimConfigChanged(Context context, int activeModemCount) {
+ synchronized (sLockProxyPhones) {
+ int prevActiveModemCount = sPhones.length;
+ if (prevActiveModemCount == activeModemCount) return;
+
+ // TODO: clean up sPhones, sCommandsInterfaces and sTelephonyNetworkFactories objects.
+ // Currently we will not clean up the 2nd Phone object, so that it can be re-used if
+ // user switches back.
+ if (prevActiveModemCount > activeModemCount) return;
+
+ sPhones = copyOf(sPhones, activeModemCount);
+ sCommandsInterfaces = copyOf(sCommandsInterfaces, activeModemCount);
+ sTelephonyNetworkFactories = copyOf(sTelephonyNetworkFactories, activeModemCount);
+
+ int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
+ for (int i = prevActiveModemCount; i < activeModemCount; i++) {
+ sCommandsInterfaces[i] = new RIL(context, RILConstants.PREFERRED_NETWORK_MODE,
+ cdmaSubscription, i);
+ sPhones[i] = createPhone(context, i);
+ if (context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_IMS)) {
+ sPhones[i].startMonitoringImsService();
+ }
+ sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
+ Looper.myLooper(), sPhones[i]);
+ }
+ }
+ }
+
+ private static Phone createPhone(Context context, int phoneId) {
+ int phoneType = TelephonyManager.getPhoneType(RILConstants.PREFERRED_NETWORK_MODE);
+ Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " phoneId = " + phoneId);
+
+ // We always use PHONE_TYPE_CDMA_LTE now.
+ if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE;
+
+ return new GsmCdmaPhone(context,
+ sCommandsInterfaces[phoneId], sPhoneNotifier, phoneId, phoneType,
+ TelephonyComponentFactory.getInstance());
+ }
+
@UnsupportedAppUsage
public static Phone getDefaultPhone() {
synchronized (sLockProxyPhones) {
@@ -462,6 +489,15 @@
}
/**
+ * Get Command Interfaces.
+ */
+ public static CommandsInterface[] getCommandsInterfaces() {
+ synchronized (sLockProxyPhones) {
+ return sCommandsInterfaces;
+ }
+ }
+
+ /**
* Adds a local log category.
*
* Only used within the telephony process. Use localLog to add log entries.
@@ -538,16 +574,6 @@
pw.decreaseIndent();
pw.println("++++++++++++++++++++++++++++++++");
- pw.println("SubscriptionMonitor:");
- pw.increaseIndent();
- try {
- sSubscriptionMonitor.dump(fd, pw, args);
- } catch (Exception e) {
- e.printStackTrace();
- }
- pw.decreaseIndent();
- pw.println("++++++++++++++++++++++++++++++++");
-
pw.println("UiccController:");
pw.increaseIndent();
try {
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index c5b7eda..363e8ff 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -43,13 +43,10 @@
private static final boolean VDBG = false; // STOPSHIP if true
@UnsupportedAppUsage
- private final Phone[] mPhone;
- @UnsupportedAppUsage
private final Context mContext;
private final AppOpsManager mAppOps;
- public PhoneSubInfoController(Context context, Phone[] phone) {
- mPhone = phone;
+ public PhoneSubInfoController(Context context) {
if (ServiceManager.getService("iphonesubinfo") == null) {
ServiceManager.addService("iphonesubinfo", this);
}
@@ -79,7 +76,7 @@
public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int subId, int keyType,
String callingPackage) {
- return callPhoneMethodForSubIdWithReadCheck(subId, callingPackage,
+ return callPhoneMethodForSubIdWithPrivilegedCheck(subId,
"getCarrierInfoForImsiEncryption",
(phone)-> phone.getCarrierInfoForImsiEncryption(keyType));
}
@@ -103,14 +100,13 @@
*/
public void resetCarrierKeysForImsiEncryption(int subId, String callingPackage) {
callPhoneMethodForSubIdWithModifyCheck(subId, callingPackage,
- "setCarrierInfoForImsiEncryption",
+ "resetCarrierKeysForImsiEncryption",
(phone)-> {
phone.resetCarrierKeysForImsiEncryption();
return null;
});
}
-
public String getDeviceSvn(String callingPackage) {
return getDeviceSvnUsingSubId(getDefaultSubscription(), callingPackage);
}
@@ -222,7 +218,7 @@
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
phoneId = 0;
}
- return mPhone[phoneId];
+ return PhoneFactory.getPhone(phoneId);
}
/**
@@ -434,7 +430,6 @@
aContext, aSubId, aCallingPackage, aMessage));
}
-
private <T> T callPhoneMethodForSubIdWithPrivilegedCheck(
int subId, String message, CallPhoneMethodHelper<T> callMethodHelper) {
return callPhoneMethodWithPermissionCheck(subId, null, message, callMethodHelper,
@@ -467,7 +462,7 @@
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
phoneId = 0;
}
- final Phone phone = mPhone[phoneId];
+ final Phone phone = PhoneFactory.getPhone(phoneId);
if (phone == null) {
return null;
}
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index cf64a8b..ae514d9 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -25,6 +25,8 @@
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
+import static java.util.Arrays.copyOf;
+
import android.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -46,13 +48,13 @@
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.telephony.data.ApnSetting;
import android.util.LocalLog;
@@ -154,15 +156,10 @@
private final List<DcRequest> mPrioritizedDcRequests = new ArrayList<DcRequest>();
private final RegistrantList mActivePhoneRegistrants;
private final SubscriptionController mSubscriptionController;
- private final int[] mPhoneSubscriptions;
- private final CommandsInterface[] mCommandsInterfaces;
private final Context mContext;
- private final PhoneState[] mPhoneStates;
- @UnsupportedAppUsage
- private final int mNumPhones;
- @UnsupportedAppUsage
- private final Phone[] mPhones;
private final LocalLog mLocalLog;
+ private PhoneState[] mPhoneStates;
+ private int[] mPhoneSubscriptions;
@VisibleForTesting
public final PhoneStateListener mPhoneStateListener;
private final CellularNetworkValidator mValidator;
@@ -170,8 +167,14 @@
public final CellularNetworkValidator.ValidationCallback mValidationCallback =
(validated, subId) -> Message.obtain(PhoneSwitcher.this,
EVENT_NETWORK_VALIDATION_DONE, subId, validated ? 1 : 0).sendToTarget();
+
@UnsupportedAppUsage
- private int mMaxActivePhones;
+ // How many phones (correspondingly logical modems) are allowed for PS attach. This is used
+ // when we specifically use setDataAllowed to initiate on-demand PS(data) attach for each phone.
+ private int mMaxDataAttachModemCount;
+ // Local cache of TelephonyManager#getActiveModemCount(). 1 if in single SIM mode, 2 if in dual
+ // SIM mode.
+ private int mActiveModemCount;
private static PhoneSwitcher sPhoneSwitcher = null;
// Which primary (non-opportunistic) subscription is set as data subscription among all primary
@@ -237,6 +240,9 @@
private static final int EVENT_OVERRIDE_DDS_FOR_EMERGENCY = 115;
// If it exists, remove the current mEmergencyOverride DDS override.
private static final int EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE = 116;
+ // If it exists, remove the current mEmergencyOverride DDS override.
+ @VisibleForTesting
+ public static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 117;
// Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's
// 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse
@@ -288,47 +294,21 @@
/**
* Method to create singleton instance.
*/
- public static PhoneSwitcher make(int maxActivePhones, int numPhones, Context context,
- SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
- CommandsInterface[] cis, Phone[] phones) {
+ public static PhoneSwitcher make(int maxDataAttachModemCount, Context context, Looper looper) {
if (sPhoneSwitcher == null) {
- sPhoneSwitcher = new PhoneSwitcher(maxActivePhones, numPhones, context,
- subscriptionController, looper, tr, cis, phones);
+ sPhoneSwitcher = new PhoneSwitcher(maxDataAttachModemCount, context, looper);
}
return sPhoneSwitcher;
}
- /** This constructor is only used for testing purpose. */
- @VisibleForTesting
- public PhoneSwitcher(int numPhones, Looper looper) {
- super(looper);
- mMaxActivePhones = 0;
- mSubscriptionController = null;
- mCommandsInterfaces = null;
- mContext = null;
- mPhoneStates = null;
- mPhones = null;
- mLocalLog = null;
- mActivePhoneRegistrants = null;
- mNumPhones = numPhones;
- mPhoneSubscriptions = new int[numPhones];
- mRadioConfig = RadioConfig.getInstance(mContext);
- mPhoneStateListener = new PhoneStateListener(looper) {
- public void onPhoneCapabilityChanged(PhoneCapability capability) {
- onPhoneCapabilityChangedInternal(capability);
- }
- };
- mValidator = CellularNetworkValidator.getInstance();
- }
-
private boolean isPhoneInVoiceCallChanged() {
int oldPhoneIdInVoiceCall = mPhoneIdInVoiceCall;
// If there's no active call, the value will become INVALID_PHONE_INDEX
// and internet data will be switched back to system selected or user selected
// subscription.
mPhoneIdInVoiceCall = SubscriptionManager.INVALID_PHONE_INDEX;
- for (Phone phone : mPhones) {
+ for (Phone phone : PhoneFactory.getPhones()) {
if (isPhoneInVoiceCall(phone) || isPhoneInVoiceCall(phone.getImsPhone())) {
mPhoneIdInVoiceCall = phone.getPhoneId();
break;
@@ -345,18 +325,16 @@
}
@VisibleForTesting
- public PhoneSwitcher(int maxActivePhones, int numPhones, Context context,
- SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
- CommandsInterface[] cis, Phone[] phones) {
+ public PhoneSwitcher(int maxActivePhones, Context context, Looper looper) {
super(looper);
mContext = context;
- mNumPhones = numPhones;
- mPhones = phones;
- mPhoneSubscriptions = new int[numPhones];
- mMaxActivePhones = maxActivePhones;
+ mActiveModemCount = getTm().getActiveModemCount();
+ mPhoneSubscriptions = new int[mActiveModemCount];
+ mPhoneStates = new PhoneState[mActiveModemCount];
+ mMaxDataAttachModemCount = maxActivePhones;
mLocalLog = new LocalLog(MAX_LOCAL_LOG_LINES);
- mSubscriptionController = subscriptionController;
+ mSubscriptionController = SubscriptionController.getInstance();
mRadioConfig = RadioConfig.getInstance(mContext);
mPhoneStateListener = new PhoneStateListener(looper) {
@@ -369,34 +347,31 @@
mValidator = CellularNetworkValidator.getInstance();
mActivePhoneRegistrants = new RegistrantList();
- mPhoneStates = new PhoneState[numPhones];
- for (int i = 0; i < numPhones; i++) {
+ for (int i = 0; i < mActiveModemCount; i++) {
mPhoneStates[i] = new PhoneState();
- if (mPhones[i] != null) {
- mPhones[i].registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
+ if (PhoneFactory.getPhone(i) != null) {
+ PhoneFactory.getPhone(i).registerForEmergencyCallToggle(
+ this, EVENT_EMERGENCY_TOGGLE, null);
// TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone.
- mPhones[i].registerForPreciseCallStateChanged(
+ PhoneFactory.getPhone(i).registerForPreciseCallStateChanged(
this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
- if (mPhones[i].getImsPhone() != null) {
- mPhones[i].getImsPhone().registerForPreciseCallStateChanged(
+ if (PhoneFactory.getPhone(i).getImsPhone() != null) {
+ PhoneFactory.getPhone(i).getImsPhone().registerForPreciseCallStateChanged(
this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
}
- mPhones[i].getDataEnabledSettings().registerForDataEnabledChanged(
+ PhoneFactory.getPhone(i).getDataEnabledSettings().registerForDataEnabledChanged(
this, EVENT_DATA_ENABLED_CHANGED, null);
}
}
- mCommandsInterfaces = cis;
-
- if (numPhones > 0) {
- mCommandsInterfaces[0].registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
+ if (mActiveModemCount > 0) {
+ PhoneFactory.getPhone(0).mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
}
- try {
- tr.addOnSubscriptionsChangedListener(context.getOpPackageName(),
- mSubscriptionsChangedListener);
- } catch (RemoteException e) {
- }
+ TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
+ context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+ telephonyRegistryManager.addOnSubscriptionsChangedListener(
+ mSubscriptionsChangedListener, mSubscriptionsChangedListener.getHandlerExecutor());
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -404,6 +379,9 @@
mContext.registerReceiver(mDefaultDataChangedReceiver,
new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
+ PhoneConfigurationManager.registerForMultiSimConfigChange(
+ this, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
+
NetworkCapabilities netCap = new NetworkCapabilities();
netCap.addTransportType(TRANSPORT_CELLULAR);
netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
@@ -438,8 +416,8 @@
}
};
- private final IOnSubscriptionsChangedListener mSubscriptionsChangedListener =
- new IOnSubscriptionsChangedListener.Stub() {
+ private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
@Override
public void onSubscriptionsChanged() {
Message msg = PhoneSwitcher.this.obtainMessage(EVENT_SUBSCRIPTION_CHANGED);
@@ -619,11 +597,43 @@
onEvaluate(REQUESTS_UNCHANGED, "emer_rm_override_dds");
break;
}
+ case EVENT_MULTI_SIM_CONFIG_CHANGED: {
+ int activeModemCount = (int) ((AsyncResult) msg.obj).result;
+ onMultiSimConfigChanged(activeModemCount);
+ break;
+ }
+ }
+ }
+
+ private synchronized void onMultiSimConfigChanged(int activeModemCount) {
+ // No change.
+ if (mActiveModemCount == activeModemCount) return;
+ int oldActiveModemCount = mActiveModemCount;
+ mActiveModemCount = activeModemCount;
+
+ mPhoneSubscriptions = copyOf(mPhoneSubscriptions, mActiveModemCount);
+ mPhoneStates = copyOf(mPhoneStates, mActiveModemCount);
+
+ // Single SIM -> dual SIM switch.
+ for (int phoneId = oldActiveModemCount; phoneId < mActiveModemCount; phoneId++) {
+ mPhoneStates[phoneId] = new PhoneState();
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ if (phone == null) continue;
+
+ phone.registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
+ // TODO (b/135566422): combine register for both GsmCdmaPhone and ImsPhone.
+ phone.registerForPreciseCallStateChanged(this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+ if (phone.getImsPhone() != null) {
+ phone.getImsPhone().registerForPreciseCallStateChanged(
+ this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+ }
+ phone.getDataEnabledSettings().registerForDataEnabledChanged(
+ this, EVENT_DATA_ENABLED_CHANGED, null);
}
}
private boolean isInEmergencyCallbackMode() {
- for (Phone p : mPhones) {
+ for (Phone p : PhoneFactory.getPhones()) {
if (p == null) continue;
if (p.isInEcm()) return true;
Phone imsPhone = p.getImsPhone();
@@ -698,7 +708,7 @@
private void collectRequestNetworkMetrics(NetworkRequest networkRequest) {
// Request network for MMS will temporary disable the network on default data subscription,
// this only happen on multi-sim device.
- if (mNumPhones > 1 && networkRequest.networkCapabilities.hasCapability(
+ if (mActiveModemCount > 1 && networkRequest.networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_MMS)) {
OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
@@ -710,7 +720,7 @@
private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) {
// Release network for MMS will recover the network on default data subscription, this only
// happen on multi-sim device.
- if (mNumPhones > 1 && networkRequest.networkCapabilities.hasCapability(
+ if (mActiveModemCount > 1 && networkRequest.networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_MMS)) {
OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
@@ -719,6 +729,10 @@
}
}
+ private TelephonyManager getTm() {
+ return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
private static final boolean REQUESTS_CHANGED = true;
private static final boolean REQUESTS_UNCHANGED = false;
/**
@@ -748,7 +762,7 @@
boolean hasAnyActiveSubscription = false;
// Check if phoneId to subId mapping is changed.
- for (int i = 0; i < mNumPhones; i++) {
+ for (int i = 0; i < mActiveModemCount; i++) {
int sub = mSubscriptionController.getSubIdUsingPhoneId(i);
if (SubscriptionManager.isValidSubscriptionId(sub)) hasAnyActiveSubscription = true;
@@ -789,7 +803,7 @@
// With HAL_COMMAND_PREFERRED_DATA, all phones are assumed to allow PS attach.
// So marking all phone as active, and the phone with mPreferredDataPhoneId
// will send radioConfig command.
- for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
+ for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) {
mPhoneStates[phoneId].active = true;
}
sendRilCommands(mPreferredDataPhoneId);
@@ -801,9 +815,9 @@
* Otherwise, choose to activate phones according to requests. And
* if list is not full, add mPreferredDataPhoneId.
*/
- if (mMaxActivePhones == mPhones.length) {
- for (int i = 0; i < mMaxActivePhones; i++) {
- newActivePhones.add(mPhones[i].getPhoneId());
+ if (mMaxDataAttachModemCount == mActiveModemCount) {
+ for (int i = 0; i < mMaxDataAttachModemCount; i++) {
+ newActivePhones.add(i);
}
} else {
// First try to activate phone in voice call.
@@ -811,17 +825,17 @@
newActivePhones.add(mPhoneIdInVoiceCall);
}
- if (newActivePhones.size() < mMaxActivePhones) {
+ if (newActivePhones.size() < mMaxDataAttachModemCount) {
for (DcRequest dcRequest : mPrioritizedDcRequests) {
int phoneIdForRequest = phoneIdForRequest(dcRequest.networkRequest);
if (phoneIdForRequest == INVALID_PHONE_INDEX) continue;
if (newActivePhones.contains(phoneIdForRequest)) continue;
newActivePhones.add(phoneIdForRequest);
- if (newActivePhones.size() >= mMaxActivePhones) break;
+ if (newActivePhones.size() >= mMaxDataAttachModemCount) break;
}
}
- if (newActivePhones.size() < mMaxActivePhones
+ if (newActivePhones.size() < mMaxDataAttachModemCount
&& newActivePhones.contains(mPreferredDataPhoneId)
&& SubscriptionManager.isUsableSubIdValue(mPreferredDataPhoneId)) {
newActivePhones.add(mPreferredDataPhoneId);
@@ -831,14 +845,14 @@
if (VDBG) {
log("mPrimaryDataSubId = " + mPrimaryDataSubId);
log("mOpptDataSubId = " + mOpptDataSubId);
- for (int i = 0; i < mNumPhones; i++) {
+ for (int i = 0; i < mActiveModemCount; i++) {
log(" phone[" + i + "] using sub[" + mPhoneSubscriptions[i] + "]");
}
log(" newActivePhones:");
for (Integer i : newActivePhones) log(" " + i);
}
- for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
+ for (int phoneId = 0; phoneId < mActiveModemCount; phoneId++) {
if (!newActivePhones.contains(phoneId)) {
deactivate(phoneId);
}
@@ -887,7 +901,7 @@
* want to resend setDataAllowed or setPreferredDataSubscriptionId
*/
public void onRadioCapChanged(int phoneId) {
- validatePhoneId(phoneId);
+ if (!SubscriptionManager.isValidPhoneId(phoneId)) return;
Message msg = obtainMessage(EVENT_RADIO_CAPABILITY_CHANGED);
msg.arg1 = phoneId;
msg.sendToTarget();
@@ -912,7 +926,7 @@
*/
public void overrideDefaultDataForEmergency(int phoneId, int overrideTimeSec,
CompletableFuture<Boolean> dataSwitchResult) {
- validatePhoneId(phoneId);
+ if (!SubscriptionManager.isValidPhoneId(phoneId)) return;
Message msg = obtainMessage(EVENT_OVERRIDE_DDS_FOR_EMERGENCY);
EmergencyOverrideRequest request = new EmergencyOverrideRequest();
request.mPhoneId = phoneId;
@@ -923,13 +937,13 @@
}
private void sendRilCommands(int phoneId) {
- if (!SubscriptionManager.isValidPhoneId(phoneId) || phoneId >= mNumPhones) return;
+ if (!SubscriptionManager.isValidPhoneId(phoneId)) return;
Message message = Message.obtain(this, EVENT_MODEM_COMMAND_DONE, phoneId);
if (mHalCommandToUse == HAL_COMMAND_ALLOW_DATA || mHalCommandToUse == HAL_COMMAND_UNKNOWN) {
// Skip ALLOW_DATA for single SIM device
- if (mNumPhones > 1) {
- mCommandsInterfaces[phoneId].setDataAllowed(isPhoneActive(phoneId), message);
+ if (mActiveModemCount > 1) {
+ PhoneFactory.getPhone(phoneId).mCi.setDataAllowed(isPhoneActive(phoneId), message);
}
} else if (phoneId == mPreferredDataPhoneId) {
// Only setPreferredDataModem if the phoneId equals to current mPreferredDataPhoneId.
@@ -938,11 +952,11 @@
}
private void onPhoneCapabilityChangedInternal(PhoneCapability capability) {
- int newMaxActivePhones = TelephonyManager.getDefault()
+ int newMaxDataAttachModemCount = TelephonyManager.getDefault()
.getNumberOfModemsWithSimultaneousDataConnections();
- if (mMaxActivePhones != newMaxActivePhones) {
- mMaxActivePhones = newMaxActivePhones;
- log("Max active phones changed to " + mMaxActivePhones);
+ if (mMaxDataAttachModemCount != newMaxDataAttachModemCount) {
+ mMaxDataAttachModemCount = newMaxDataAttachModemCount;
+ log("Max active phones changed to " + mMaxDataAttachModemCount);
onEvaluate(REQUESTS_UNCHANGED, "phoneCfgChanged");
}
}
@@ -954,7 +968,8 @@
if (subId == DEFAULT_SUBSCRIPTION_ID) return mPreferredDataPhoneId;
if (subId == INVALID_SUBSCRIPTION_ID) return INVALID_PHONE_INDEX;
- int preferredDataSubId = SubscriptionManager.isValidPhoneId(mPreferredDataPhoneId)
+ int preferredDataSubId = (mPreferredDataPhoneId >= 0
+ && mPreferredDataPhoneId < mActiveModemCount)
? mPhoneSubscriptions[mPreferredDataPhoneId] : INVALID_SUBSCRIPTION_ID;
// Currently we assume multi-SIM devices will only support one Internet PDN connection. So
@@ -972,7 +987,7 @@
// Try to find matching phone ID. If it doesn't exist, we'll end up returning INVALID.
int phoneId = INVALID_PHONE_INDEX;
- for (int i = 0; i < mNumPhones; i++) {
+ for (int i = 0; i < mActiveModemCount; i++) {
if (mPhoneSubscriptions[i] == subId) {
phoneId = i;
break;
@@ -1035,7 +1050,7 @@
int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
if (SubscriptionManager.isUsableSubIdValue(subId)) {
- for (int i = 0; i < mNumPhones; i++) {
+ for (int i = 0; i < mActiveModemCount; i++) {
if (mPhoneSubscriptions[i] == subId) {
phoneId = i;
break;
@@ -1050,7 +1065,7 @@
}
private void transitionToEmergencyPhone() {
- if (mNumPhones <= 0) {
+ if (mActiveModemCount <= 0) {
log("No phones: unable to reset preferred phone for emergency");
return;
}
@@ -1067,14 +1082,15 @@
}
private Phone findPhoneById(final int phoneId) {
- if (phoneId < 0 || phoneId >= mNumPhones) {
+ if (!SubscriptionManager.isValidPhoneId(phoneId)) {
return null;
}
- return mPhones[phoneId];
+ return PhoneFactory.getPhone(phoneId);
}
- public boolean shouldApplyNetworkRequest(NetworkRequest networkRequest, int phoneId) {
- validatePhoneId(phoneId);
+ public synchronized boolean shouldApplyNetworkRequest(
+ NetworkRequest networkRequest, int phoneId) {
+ if (!SubscriptionManager.isValidPhoneId(phoneId)) return false;
// In any case, if phone state is inactive, don't apply the network request.
if (!isPhoneActive(phoneId) || (
@@ -1111,13 +1127,6 @@
mActivePhoneRegistrants.remove(h);
}
- @VisibleForTesting
- protected void validatePhoneId(int phoneId) {
- if (phoneId < 0 || phoneId >= mNumPhones) {
- throw new IllegalArgumentException("Invalid PhoneId");
- }
- }
-
/**
* Set opportunistic data subscription. It's an indication to switch Internet data to this
* subscription. It has to be an active subscription, and PhoneSwitcher will try to validate
@@ -1301,14 +1310,10 @@
* See {@link PhoneStateListener#LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE}.
*/
private void notifyPreferredDataSubIdChanged() {
- ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
- "telephony.registry"));
- try {
- log("notifyPreferredDataSubIdChanged to " + mPreferredDataSubId);
- tr.notifyActiveDataSubIdChanged(mPreferredDataSubId);
- } catch (RemoteException ex) {
- // Should never happen because its always available.
- }
+ TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) mContext
+ .getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+ log("notifyPreferredDataSubIdChanged to " + mPreferredDataSubId);
+ telephonyRegistryManager.notifyActiveDataSubIdChanged(mPreferredDataSubId);
}
/**
@@ -1322,7 +1327,7 @@
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
pw.println("PhoneSwitcher:");
Calendar c = Calendar.getInstance();
- for (int i = 0; i < mNumPhones; i++) {
+ for (int i = 0; i < mActiveModemCount; i++) {
PhoneState ps = mPhoneStates[i];
c.setTimeInMillis(ps.lastRequested);
pw.println("PhoneId(" + i + ") active=" + ps.active + ", lastRequest=" +
diff --git a/src/java/com/android/internal/telephony/ProxyController.java b/src/java/com/android/internal/telephony/ProxyController.java
index 54fcac9..69f8a0b 100644
--- a/src/java/com/android/internal/telephony/ProxyController.java
+++ b/src/java/com/android/internal/telephony/ProxyController.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony;
+import static java.util.Arrays.copyOf;
+
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +32,7 @@
import android.telephony.TelephonyManager;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ims.RcsMessageController;
import java.util.ArrayList;
@@ -40,11 +43,13 @@
public class ProxyController {
static final String LOG_TAG = "ProxyController";
- private static final int EVENT_NOTIFICATION_RC_CHANGED = 1;
+ private static final int EVENT_NOTIFICATION_RC_CHANGED = 1;
private static final int EVENT_START_RC_RESPONSE = 2;
private static final int EVENT_APPLY_RC_RESPONSE = 3;
private static final int EVENT_FINISH_RC_RESPONSE = 4;
private static final int EVENT_TIMEOUT = 5;
+ @VisibleForTesting
+ public static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 6;
private static final int SET_RC_STATUS_IDLE = 0;
private static final int SET_RC_STATUS_STARTING = 1;
@@ -105,9 +110,9 @@
//***** Class Methods
- public static ProxyController getInstance(Context context, Phone[] phone, PhoneSwitcher ps) {
+ public static ProxyController getInstance(Context context) {
if (sProxyController == null) {
- sProxyController = new ProxyController(context, phone, ps);
+ sProxyController = new ProxyController(context);
}
return sProxyController;
}
@@ -117,17 +122,17 @@
return sProxyController;
}
- private ProxyController(Context context, Phone[] phone, PhoneSwitcher phoneSwitcher) {
+ private ProxyController(Context context) {
logd("Constructor - Enter");
mContext = context;
- mPhones = phone;
- mPhoneSwitcher = phoneSwitcher;
+ mPhones = PhoneFactory.getPhones();
+ mPhoneSwitcher = PhoneSwitcher.getInstance();
RcsMessageController.init(context);
- mUiccPhoneBookController = new UiccPhoneBookController(mPhones);
- mPhoneSubInfoController = new PhoneSubInfoController(mContext, mPhones);
+ mUiccPhoneBookController = new UiccPhoneBookController();
+ mPhoneSubInfoController = new PhoneSubInfoController(mContext);
mSmsController = new SmsController(mContext);
mSetRadioAccessFamilyStatus = new int[mPhones.length];
mNewRadioAccessFamily = new int[mPhones.length];
@@ -146,6 +151,9 @@
mPhones[i].registerForRadioCapabilityChanged(
mHandler, EVENT_NOTIFICATION_RC_CHANGED, null);
}
+
+ PhoneConfigurationManager.registerForMultiSimConfigChange(
+ mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
logd("Constructor - Exit");
}
@@ -201,7 +209,7 @@
*/
public boolean setRadioCapability(RadioAccessFamily[] rafs) {
if (rafs.length != mPhones.length) {
- throw new RuntimeException("Length of input rafs must equal to total phone count");
+ return false;
}
// Check if there is any ongoing transaction and throw an exception if there
// is one as this is a programming error.
@@ -291,7 +299,8 @@
return true;
}
- private Handler mHandler = new Handler() {
+ @VisibleForTesting
+ public final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
logd("handleMessage msg.what=" + msg.what);
@@ -316,12 +325,37 @@
onTimeoutRadioCapability(msg);
break;
+ case EVENT_MULTI_SIM_CONFIG_CHANGED:
+ onMultiSimConfigChanged();
+ break;
+
default:
break;
}
}
};
+ private void onMultiSimConfigChanged() {
+ int oldPhoneCount = mPhones.length;
+ mPhones = PhoneFactory.getPhones();
+
+ // Re-size arrays.
+ mSetRadioAccessFamilyStatus = copyOf(mSetRadioAccessFamilyStatus, mPhones.length);
+ mNewRadioAccessFamily = copyOf(mNewRadioAccessFamily, mPhones.length);
+ mOldRadioAccessFamily = copyOf(mOldRadioAccessFamily, mPhones.length);
+ mCurrentLogicalModemIds = copyOf(mCurrentLogicalModemIds, mPhones.length);
+ mNewLogicalModemIds = copyOf(mNewLogicalModemIds, mPhones.length);
+
+ // Clear to be sure we're in the initial state
+ clearTransaction();
+
+ // Register radio cap change for new phones.
+ for (int i = oldPhoneCount; i < mPhones.length; i++) {
+ mPhones[i].registerForRadioCapabilityChanged(
+ mHandler, EVENT_NOTIFICATION_RC_CHANGED, null);
+ }
+ }
+
/**
* Handle START response
* @param msg obj field isa RadioCapability
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index c293a09..195da41 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -91,6 +91,7 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.PrefNetworkMode;
@@ -413,7 +414,7 @@
/** Returns a {@link IRadio} instance or null if the service is not available. */
@VisibleForTesting
public synchronized IRadio getRadioProxy(Message result) {
- if (!PhoneConfigurationManager.isPhoneActive(mPhoneId)) return null;
+ if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return null;
if (!mIsMobileNetworkSupported) {
if (RILJ_LOGV) riljLog("getRadioProxy: Not calling getService(): wifi-only");
if (result != null) {
@@ -510,13 +511,15 @@
// Try to connect to RIL services and set response functions.
getRadioProxy(null);
getOemHookProxy(null);
+ } else {
+ resetProxyAndRequestList();
}
}
/** Returns an {@link IOemHook} instance or null if the service is not available. */
@VisibleForTesting
public synchronized IOemHook getOemHookProxy(Message result) {
- if (!PhoneConfigurationManager.isPhoneActive(mPhoneId)) return null;
+ if (!SubscriptionManager.isValidPhoneId((mPhoneId))) return null;
if (!mIsMobileNetworkSupported) {
if (RILJ_LOGV) riljLog("getOemHookProxy: Not calling getService(): wifi-only");
if (result != null) {
diff --git a/src/java/com/android/internal/telephony/RatRatcheter.java b/src/java/com/android/internal/telephony/RatRatcheter.java
index 7b45c53..6216200 100644
--- a/src/java/com/android/internal/telephony/RatRatcheter.java
+++ b/src/java/com/android/internal/telephony/RatRatcheter.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.telephony.AccessNetworkConstants;
@@ -83,8 +84,14 @@
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- phone.getContext().registerReceiverAsUser(mConfigChangedReceiver, UserHandle.ALL,
- intentFilter, null, null);
+ try {
+ Context contextAsUser = phone.getContext().createPackageContextAsUser(
+ phone.getContext().getPackageName(), 0, UserHandle.ALL);
+ contextAsUser.registerReceiver(mConfigChangedReceiver,
+ intentFilter, null /* broadcastPermission */, null);
+ } catch (PackageManager.NameNotFoundException e) {
+ Rlog.e(LOG_TAG, "Package name not found: " + e.getMessage());
+ }
resetRatFamilyMap();
}
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 0f3d8aa..4b32c72 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -30,7 +30,6 @@
import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
-import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -383,13 +382,6 @@
}
}
- private static int getSendSmsFlag(@Nullable PendingIntent deliveryIntent) {
- if (deliveryIntent == null) {
- return 0;
- }
- return CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS;
- }
-
/**
* Use the carrier messaging service to send a text SMS.
*/
@@ -405,8 +397,13 @@
if (text != null) {
try {
- sendTextSms(text, getSubId(),
- mTracker.mDestAddress, getSendSmsFlag(mTracker.mDeliveryIntent),
+ sendTextSms(
+ text,
+ getSubId(),
+ mTracker.mDestAddress,
+ (mTracker.mDeliveryIntent != null)
+ ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
+ : 0,
mSenderCallback);
} catch (RuntimeException e) {
Rlog.e(TAG, "Exception sending the SMS: " + e);
@@ -438,9 +435,15 @@
if (data != null) {
try {
- sendDataSms(data, getSubId(),
- mTracker.mDestAddress, destPort,
- getSendSmsFlag(mTracker.mDeliveryIntent), mSenderCallback);
+ sendDataSms(
+ data,
+ getSubId(),
+ mTracker.mDestAddress,
+ destPort,
+ (mTracker.mDeliveryIntent != null)
+ ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
+ : 0,
+ mSenderCallback);
} catch (RuntimeException e) {
Rlog.e(TAG, "Exception sending the SMS: " + e);
mSenderCallback.onSendSmsComplete(
@@ -566,10 +569,23 @@
@Override
public void onServiceReady() {
+ boolean statusReportRequested = false;
+ for (SmsTracker tracker : mTrackers) {
+ if (tracker.mDeliveryIntent != null) {
+ statusReportRequested = true;
+ break;
+ }
+ }
+
try {
sendMultipartTextSms(
- mParts, getSubId(), mTrackers[0].mDestAddress,
- getSendSmsFlag(mTrackers[0].mDeliveryIntent), mSenderCallback);
+ mParts,
+ getSubId(),
+ mTrackers[0].mDestAddress,
+ statusReportRequested
+ ? CarrierMessagingService.SEND_FLAG_REQUEST_DELIVERY_STATUS
+ : 0,
+ mSenderCallback);
} catch (RuntimeException e) {
Rlog.e(TAG, "Exception sending the SMS: " + e);
mSenderCallback.onSendMultipartSmsComplete(
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index bcfceff..029088f 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -57,6 +57,7 @@
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityCdma;
@@ -71,7 +72,6 @@
import android.telephony.PhysicalChannelConfig;
import android.telephony.Rlog;
import android.telephony.ServiceState;
-import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -728,7 +728,8 @@
mMin = null;
mPrlVersion = null;
mIsMinInfoReady = false;
- mNitzState.handleNetworkCountryCodeUnavailable();
+ mLastNitzData = null;
+ mNitzState.handleNetworkUnavailable();
mCellIdentity = null;
mNewCellIdentity = null;
mSignalStrengthUpdatedTime = System.currentTimeMillis();
@@ -3014,7 +3015,8 @@
mNewSS.setStateOutOfService();
mNewCellIdentity = null;
setSignalStrengthDefaultValues();
- mNitzState.handleNetworkCountryCodeUnavailable();
+ mLastNitzData = null;
+ mNitzState.handleNetworkUnavailable();
pollStateDone();
break;
@@ -3022,7 +3024,8 @@
mNewSS.setStateOff();
mNewCellIdentity = null;
setSignalStrengthDefaultValues();
- mNitzState.handleNetworkCountryCodeUnavailable();
+ mLastNitzData = null;
+ mNitzState.handleNetworkUnavailable();
// don't poll when device is shutting down or the poll was not modemTrigged
// (they sent us new radio data) and current network is not IWLAN
if (mDeviceShuttingDown ||
@@ -4716,6 +4719,9 @@
mPhone.setSignalStrengthReportingCriteria(
config.getIntArray(CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY),
AccessNetworkType.UTRAN);
+ mPhone.setSignalStrengthReportingCriteria(
+ config.getIntArray(CarrierConfigManager.KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY),
+ AccessNetworkType.GERAN);
}
private void updateServiceStateLteEarfcnBoost(ServiceState serviceState, int lteEarfcn) {
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 0fce4d2..eaa7fc8 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -551,9 +551,6 @@
}
}
- /**
- * Triggered by `adb shell dumpsys isms`
- */
@Override
public String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage) {
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
@@ -579,6 +576,9 @@
}
}
+ /**
+ * Triggered by `adb shell dumpsys isms`
+ */
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!checkDumpPermission(mContext, LOG_TAG, pw)) {
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index 6b7c8a3..66b8709 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -432,82 +432,81 @@
*/
public void sendRetrySms(SMSDispatcher.SmsTracker tracker) {
String oldFormat = tracker.mFormat;
+ boolean retryUsingImsService = false;
- // newFormat will be based on voice technology
+ if (!tracker.mUsesImsServiceForIms && mImsSmsDispatcher.isAvailable()) {
+ // If this tracker has not been handled by ImsSmsDispatcher yet and IMS Service is
+ // available now, retry this failed tracker using IMS Service.
+ retryUsingImsService = true;
+ }
+
+ // If retryUsingImsService is true, newFormat will be IMS SMS format. Otherwise, newFormat
+ // will be based on voice technology.
String newFormat =
- (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType())
- ? mCdmaDispatcher.getFormat() : mGsmDispatcher.getFormat();
+ retryUsingImsService
+ ? mImsSmsDispatcher.getFormat()
+ : (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType())
+ ? mCdmaDispatcher.getFormat()
+ : mGsmDispatcher.getFormat();
- // was previously sent sms format match with voice tech?
- if (oldFormat.equals(newFormat)) {
- if (isCdmaFormat(newFormat)) {
- Rlog.d(TAG, "old format matched new format (cdma)");
- mCdmaDispatcher.sendSms(tracker);
- return;
- } else {
- Rlog.d(TAG, "old format matched new format (gsm)");
- mGsmDispatcher.sendSms(tracker);
+ Rlog.d(TAG, "old format(" + oldFormat + ") ==> new format (" + newFormat + ")");
+ if (!oldFormat.equals(newFormat)) {
+ // format didn't match, need to re-encode.
+ HashMap map = tracker.getData();
+
+ // to re-encode, fields needed are: scAddr, destAddr and text if originally sent as
+ // sendText or data and destPort if originally sent as sendData.
+ if (!(map.containsKey("scAddr") && map.containsKey("destAddr")
+ && (map.containsKey("text")
+ || (map.containsKey("data") && map.containsKey("destPort"))))) {
+ // should never come here...
+ Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
+ tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
return;
}
- }
+ String scAddr = (String) map.get("scAddr");
+ String destAddr = (String) map.get("destAddr");
- // format didn't match, need to re-encode.
- HashMap map = tracker.getData();
+ SmsMessageBase.SubmitPduBase pdu = null;
+ // figure out from tracker if this was sendText/Data
+ if (map.containsKey("text")) {
+ Rlog.d(TAG, "sms failed was text");
+ String text = (String) map.get("text");
- // to re-encode, fields needed are: scAddr, destAddr, and
- // text if originally sent as sendText or
- // data and destPort if originally sent as sendData.
- if (!(map.containsKey("scAddr") && map.containsKey("destAddr")
- && (map.containsKey("text")
- || (map.containsKey("data") && map.containsKey("destPort"))))) {
- // should never come here...
- Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
- tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
- return;
- }
- String scAddr = (String) map.get("scAddr");
- String destAddr = (String) map.get("destAddr");
+ if (isCdmaFormat(newFormat)) {
+ pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
+ scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
+ } else {
+ pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
+ scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
+ }
+ } else if (map.containsKey("data")) {
+ Rlog.d(TAG, "sms failed was data");
+ byte[] data = (byte[]) map.get("data");
+ Integer destPort = (Integer) map.get("destPort");
- SmsMessageBase.SubmitPduBase pdu = null;
- // figure out from tracker if this was sendText/Data
- if (map.containsKey("text")) {
- Rlog.d(TAG, "sms failed was text");
- String text = (String) map.get("text");
-
- if (isCdmaFormat(newFormat)) {
- Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
- pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
- scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
- } else {
- Rlog.d(TAG, "old format (cdma) ==> new format (gsm)");
- pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
- scAddr, destAddr, text, (tracker.mDeliveryIntent != null), null);
- }
- } else if (map.containsKey("data")) {
- Rlog.d(TAG, "sms failed was data");
- byte[] data = (byte[]) map.get("data");
- Integer destPort = (Integer) map.get("destPort");
-
- if (isCdmaFormat(newFormat)) {
- Rlog.d(TAG, "old format (gsm) ==> new format (cdma)");
- pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
+ if (isCdmaFormat(newFormat)) {
+ pdu = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(
scAddr, destAddr, destPort.intValue(), data,
(tracker.mDeliveryIntent != null));
- } else {
- Rlog.d(TAG, "old format (cdma) ==> new format (gsm)");
- pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
+ } else {
+ pdu = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(
scAddr, destAddr, destPort.intValue(), data,
(tracker.mDeliveryIntent != null));
+ }
}
+
+ // replace old smsc and pdu with newly encoded ones
+ map.put("smsc", pdu.encodedScAddress);
+ map.put("pdu", pdu.encodedMessage);
+ tracker.mFormat = newFormat;
}
- // replace old smsc and pdu with newly encoded ones
- map.put("smsc", pdu.encodedScAddress);
- map.put("pdu", pdu.encodedMessage);
+ SMSDispatcher dispatcher =
+ retryUsingImsService
+ ? mImsSmsDispatcher
+ : (isCdmaFormat(newFormat)) ? mCdmaDispatcher : mGsmDispatcher;
- SMSDispatcher dispatcher = (isCdmaFormat(newFormat)) ? mCdmaDispatcher : mGsmDispatcher;
-
- tracker.mFormat = dispatcher.getFormat();
dispatcher.sendSms(tracker);
}
diff --git a/src/java/com/android/internal/telephony/SmsPermissions.java b/src/java/com/android/internal/telephony/SmsPermissions.java
index 463ffe7..3aa0756 100644
--- a/src/java/com/android/internal/telephony/SmsPermissions.java
+++ b/src/java/com/android/internal/telephony/SmsPermissions.java
@@ -92,7 +92,7 @@
}
} catch (PackageManager.NameNotFoundException e) {
if (Rlog.isLoggable("SMS", Log.DEBUG)) {
- log("Cannot find configured carrier ims package");
+ loge("Cannot find configured carrier ims package");
}
}
@@ -143,7 +143,7 @@
.enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mContext, mPhone.getSubId(), message);
} catch (SecurityException e) { // To avoid crashing applications
- Log.e(LOG_TAG, message + ": Neither " + callingPackage + " is the default SMS app"
+ loge(message + ": Neither " + callingPackage + " is the default SMS app"
+ " nor the caller has "
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
+ ", or carrier privileges", e);
@@ -171,7 +171,7 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mContext, mPhone.getSubId(), message);
} catch (SecurityException e) { // To avoid crashing applications
- Log.e(LOG_TAG, message + ": Neither " + callingPackage + " is the default SMS app"
+ loge(message + ": Neither " + callingPackage + " is the default SMS app"
+ " nor the caller has " + android.Manifest.permission.MODIFY_PHONE_STATE
+ ", or carrier privileges", e);
return false;
@@ -188,6 +188,14 @@
@UnsupportedAppUsage
protected void log(String msg) {
- Log.d(LOG_TAG, "[IccSmsInterfaceManager] " + msg);
+ Rlog.d(LOG_TAG, msg);
+ }
+
+ protected void loge(String msg) {
+ Rlog.e(LOG_TAG, msg);
+ }
+
+ protected void loge(String msg, Throwable e) {
+ Rlog.e(LOG_TAG, msg, e);
}
}
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index 24bb42d..ab24988 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -133,7 +133,6 @@
/** The singleton instance. */
private static SubscriptionController sInstance = null;
- protected static Phone[] sPhones;
@UnsupportedAppUsage
protected Context mContext;
protected TelephonyManager mTelephonyManager;
@@ -1185,7 +1184,7 @@
}
// Once the records are loaded, notify DcTracker
- sPhones[slotIndex].updateDataConnectionTracker();
+ PhoneFactory.getPhone(slotIndex).updateDataConnectionTracker();
if (DBG) logdl("[addSubInfoRecord]- info size=" + sSlotIndexToSubIds.size());
}
@@ -2244,7 +2243,7 @@
}
ProxyController proxyController = ProxyController.getInstance();
- int len = sPhones.length;
+ int len = TelephonyManager.from(mContext).getActiveModemCount();
logdl("[setDefaultDataSubId] num phones=" + len + ", subId=" + subId);
if (SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -2252,7 +2251,7 @@
RadioAccessFamily[] rafs = new RadioAccessFamily[len];
boolean atLeastOneMatch = false;
for (int phoneId = 0; phoneId < len; phoneId++) {
- Phone phone = sPhones[phoneId];
+ Phone phone = PhoneFactory.getPhone(phoneId);
int raf;
int id = phone.getSubId();
if (id == subId) {
@@ -2293,11 +2292,11 @@
@UnsupportedAppUsage
private void updateAllDataConnectionTrackers() {
// Tell Phone Proxies to update data connection tracker
- int len = sPhones.length;
- if (DBG) logd("[updateAllDataConnectionTrackers] sPhones.length=" + len);
+ int len = TelephonyManager.from(mContext).getActiveModemCount();
+ if (DBG) logd("[updateAllDataConnectionTrackers] activeModemCount=" + len);
for (int phoneId = 0; phoneId < len; phoneId++) {
if (DBG) logd("[updateAllDataConnectionTrackers] phoneId=" + phoneId);
- sPhones[phoneId].updateDataConnectionTracker();
+ PhoneFactory.getPhone(phoneId).updateDataConnectionTracker();
}
}
@@ -2433,10 +2432,6 @@
}
}
- public void updatePhonesAvailability(Phone[] phones) {
- sPhones = phones;
- }
-
private synchronized ArrayList<Integer> getActiveSubIdArrayList() {
// Clone the sub id list so it can't change out from under us while iterating
List<Entry<Integer, ArrayList<Integer>>> simInfoList =
diff --git a/src/java/com/android/internal/telephony/SubscriptionMonitor.java b/src/java/com/android/internal/telephony/SubscriptionMonitor.java
deleted file mode 100644
index 33376e1..0000000
--- a/src/java/com/android/internal/telephony/SubscriptionMonitor.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-* Copyright (C) 2015 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.content.Context;
-import android.os.Handler;
-import android.os.Registrant;
-import android.os.RegistrantList;
-import android.os.RemoteException;
-import android.telephony.Rlog;
-import android.util.LocalLog;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Utility singleton to monitor subscription changes and help people act on them.
- * Uses Registrant model to post messages to handlers.
- *
- */
-public class SubscriptionMonitor {
-
- private final RegistrantList mSubscriptionsChangedRegistrants[];
-
- private final SubscriptionController mSubscriptionController;
- private final Context mContext;
-
- private final int mPhoneSubId[];
-
- private final Object mLock = new Object();
-
- private final static boolean VDBG = true;
- private final static String LOG_TAG = "SubscriptionMonitor";
-
- private final static int MAX_LOGLINES = 100;
- private final LocalLog mLocalLog = new LocalLog(MAX_LOGLINES);
-
- public SubscriptionMonitor(ITelephonyRegistry tr, Context context,
- SubscriptionController subscriptionController, int numPhones) {
- mSubscriptionController = subscriptionController;
- mContext = context;
-
- mSubscriptionsChangedRegistrants = new RegistrantList[numPhones];
- mPhoneSubId = new int[numPhones];
-
- for (int phoneId = 0; phoneId < numPhones; phoneId++) {
- mSubscriptionsChangedRegistrants[phoneId] = new RegistrantList();
- mPhoneSubId[phoneId] = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
- }
-
- try {
- tr.addOnSubscriptionsChangedListener(context.getOpPackageName(),
- mSubscriptionsChangedListener);
- } catch (RemoteException e) {
- }
- }
-
- @VisibleForTesting
- public SubscriptionMonitor() {
- mSubscriptionsChangedRegistrants = null;
- mSubscriptionController = null;
- mContext = null;
- mPhoneSubId = null;
- }
-
- private final IOnSubscriptionsChangedListener mSubscriptionsChangedListener =
- new IOnSubscriptionsChangedListener.Stub() {
- @Override
- public void onSubscriptionsChanged() {
- synchronized (mLock) {
- for (int phoneId = 0; phoneId < mPhoneSubId.length; phoneId++) {
- final int newSubId = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
- final int oldSubId = mPhoneSubId[phoneId];
- if (oldSubId != newSubId) {
- log("Phone[" + phoneId + "] subId changed " + oldSubId + "->" + newSubId
- + ", " + mSubscriptionsChangedRegistrants[phoneId].size()
- + " registrants");
- mPhoneSubId[phoneId] = newSubId;
- mSubscriptionsChangedRegistrants[phoneId].notifyRegistrants();
- }
- }
- }
- }
- };
-
- public void registerForSubscriptionChanged(int phoneId, Handler h, int what, Object o) {
- if (invalidPhoneId(phoneId)) {
- throw new IllegalArgumentException("Invalid PhoneId");
- }
- Registrant r = new Registrant(h, what, o);
- mSubscriptionsChangedRegistrants[phoneId].add(r);
- r.notifyRegistrant();
- }
-
- public void unregisterForSubscriptionChanged(int phoneId, Handler h) {
- if (invalidPhoneId(phoneId)) {
- throw new IllegalArgumentException("Invalid PhoneId");
- }
- mSubscriptionsChangedRegistrants[phoneId].remove(h);
- }
-
- private boolean invalidPhoneId(int phoneId) {
- if (phoneId >= 0 && phoneId < mPhoneSubId.length) return false;
- return true;
- }
-
- private void log(String s) {
- Rlog.d(LOG_TAG, s);
- mLocalLog.log(s);
- }
-
- public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
- synchronized (mLock) {
- mLocalLog.dump(fd, printWriter, args);
- }
- }
-}
diff --git a/src/java/com/android/internal/telephony/UiccPhoneBookController.java b/src/java/com/android/internal/telephony/UiccPhoneBookController.java
index 5a4d480..6c9fdbe 100644
--- a/src/java/com/android/internal/telephony/UiccPhoneBookController.java
+++ b/src/java/com/android/internal/telephony/UiccPhoneBookController.java
@@ -25,22 +25,17 @@
import com.android.internal.telephony.IIccPhoneBook;
import com.android.internal.telephony.uicc.AdnRecord;
-import java.lang.ArrayIndexOutOfBoundsException;
-import java.lang.NullPointerException;
import java.util.List;
public class UiccPhoneBookController extends IIccPhoneBook.Stub {
private static final String TAG = "UiccPhoneBookController";
- @UnsupportedAppUsage
- private Phone[] mPhone;
/* only one UiccPhoneBookController exists */
@UnsupportedAppUsage
- public UiccPhoneBookController(Phone[] phone) {
+ public UiccPhoneBookController() {
if (ServiceManager.getService("simphonebook") == null) {
ServiceManager.addService("simphonebook", this);
}
- mPhone = phone;
}
@Override
@@ -139,7 +134,7 @@
int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
try {
- return mPhone[phoneId].getIccPhoneBookInterfaceManager();
+ return PhoneFactory.getPhone(phoneId).getIccPhoneBookInterfaceManager();
} catch (NullPointerException e) {
Rlog.e(TAG, "Exception is :"+e.toString()+" For subscription :"+subId );
e.printStackTrace(); //To print stack trace
diff --git a/src/java/com/android/internal/telephony/WapPushOverSms.java b/src/java/com/android/internal/telephony/WapPushOverSms.java
index 776bbb6..069178d 100755
--- a/src/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/src/java/com/android/internal/telephony/WapPushOverSms.java
@@ -420,7 +420,7 @@
}
handler.dispatchIntent(intent, getPermissionForType(result.mimeType),
- getAppOpsPermissionForIntent(result.mimeType), options, receiver,
+ getAppOpsStringPermissionForIntent(result.mimeType), options, receiver,
UserHandle.SYSTEM, subId);
return Activity.RESULT_OK;
}
@@ -611,12 +611,17 @@
return permission;
}
- public static int getAppOpsPermissionForIntent(String mimeType) {
- int appOp;
+ /**
+ * Return a appOps String for the given MIME type.
+ * @param mimeType MIME type of the Intent
+ * @return The appOps String
+ */
+ public static String getAppOpsStringPermissionForIntent(String mimeType) {
+ String appOp;
if (WspTypeDecoder.CONTENT_TYPE_B_MMS.equals(mimeType)) {
- appOp = AppOpsManager.OP_RECEIVE_MMS;
+ appOp = AppOpsManager.OPSTR_RECEIVE_MMS;
} else {
- appOp = AppOpsManager.OP_RECEIVE_WAP_PUSH;
+ appOp = AppOpsManager.OPSTR_RECEIVE_WAP_PUSH;
}
return appOp;
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java b/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
index 78e7138..bdbf395 100644
--- a/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
@@ -23,6 +23,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -212,8 +213,14 @@
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- phone.getContext().registerReceiverAsUser(mConfigChangedReceiver, UserHandle.ALL,
- intentFilter, null, null);
+ try {
+ Context contextAsUser = phone.getContext().createPackageContextAsUser(
+ phone.getContext().getPackageName(), 0, UserHandle.ALL);
+ contextAsUser.registerReceiver(mConfigChangedReceiver, intentFilter,
+ null /* broadcastPermission */, null);
+ } catch (PackageManager.NameNotFoundException e) {
+ Rlog.e(TAG, "Package name not found: " + e.getMessage());
+ }
sendEmptyMessage(EVENT_BIND_QUALIFIED_NETWORKS_SERVICE);
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
index d73c900..a26b561 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony.dataconnection;
-import android.app.PendingIntent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
@@ -68,8 +67,6 @@
String mReason;
- PendingIntent mReconnectAlarmIntent;
-
/**
* user/app requested connection on this APN
*/
@@ -170,22 +167,6 @@
}
/**
- * Get the reconnect intent.
- * @return The reconnect intent
- */
- public synchronized PendingIntent getReconnectIntent() {
- return mReconnectAlarmIntent;
- }
-
- /**
- * Save the reconnect intent which can be used for cancelling later.
- * @param intent The reconnect intent
- */
- public synchronized void setReconnectIntent(PendingIntent intent) {
- mReconnectAlarmIntent = intent;
- }
-
- /**
* Get the current APN setting.
* @return APN setting
*/
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnSettingUtils.java b/src/java/com/android/internal/telephony/dataconnection/ApnSettingUtils.java
index 07d5608..8403efa 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnSettingUtils.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnSettingUtils.java
@@ -83,8 +83,8 @@
*/
public static boolean mvnoMatches(IccRecords r, int mvnoType, String mvnoMatchData) {
if (mvnoType == ApnSetting.MVNO_TYPE_SPN) {
- if ((r.getServiceProviderName() != null)
- && r.getServiceProviderName().equalsIgnoreCase(mvnoMatchData)) {
+ String spn = r.getServiceProviderNameWithBrandOverride();
+ if ((spn != null) && spn.equalsIgnoreCase(mvnoMatchData)) {
return true;
}
} else if (mvnoType == ApnSetting.MVNO_TYPE_IMSI) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 53337fd..822d249 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -45,8 +45,8 @@
import android.provider.Telephony;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.TransportType;
-import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.DataFailureCause;
import android.telephony.CarrierConfigManager;
import android.telephony.DataFailCause;
import android.telephony.NetworkRegistrationInfo;
@@ -88,6 +88,8 @@
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import libcore.net.InetAddressUtils;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -1329,6 +1331,16 @@
return result;
}
+ /** @return {@code true} if validation is required, {@code false} otherwise. */
+ public boolean isValidationRequired() {
+ final NetworkCapabilities nc = getNetworkCapabilities();
+ return nc != null
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+ }
+
/**
* @return {@code True} if 464xlat should be skipped.
*/
@@ -1357,7 +1369,11 @@
public static boolean isIpAddress(String address) {
if (address == null) return false;
- return InetAddress.isNumeric(address);
+ // Accept IPv6 addresses (only) in square brackets for compatibility.
+ if (address.startsWith("[") && address.endsWith("]") && address.indexOf(':') != -1) {
+ address = address.substring(1, address.length() - 1);
+ }
+ return InetAddressUtils.isNumericAddress(address);
}
private SetupResult setLinkProperties(DataCallResponse response,
@@ -1431,7 +1447,8 @@
for (InetAddress gateway : response.getGatewayAddresses()) {
// Allow 0.0.0.0 or :: as a gateway;
// this indicates a point-to-point interface.
- linkProperties.addRoute(new RouteInfo(gateway));
+ linkProperties.addRoute(new RouteInfo(null, gateway, null,
+ RouteInfo.RTN_UNICAST));
}
// set interface MTU
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
index 66d3064..f09d05f 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
@@ -133,9 +133,9 @@
final String[] pkgToGrant = {packageName};
try {
mPackageManager.grantDefaultPermissionsToEnabledTelephonyDataServices(
- pkgToGrant, mPhone.getContext().getUserId());
+ pkgToGrant, UserHandle.myUserId());
mAppOps.setMode(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS,
- mPhone.getContext().getUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED);
+ UserHandle.myUserId(), pkgToGrant[0], AppOpsManager.MODE_ALLOWED);
} catch (RemoteException e) {
loge("Binder to package manager died, permission grant for DataService failed.");
throw e.rethrowAsRuntimeException();
@@ -157,10 +157,9 @@
String[] dataServicesArray = new String[dataServices.size()];
dataServices.toArray(dataServicesArray);
mPackageManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices(
- dataServicesArray, mPhone.getContext().getUserId());
+ dataServicesArray, UserHandle.myUserId());
for (String pkg : dataServices) {
- mAppOps.setMode(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS,
- mPhone.getContext().getUserId(),
+ mAppOps.setMode(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS, UserHandle.myUserId(),
pkg, AppOpsManager.MODE_ERRORED);
}
} catch (RemoteException e) {
@@ -287,7 +286,14 @@
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
-
+ try {
+ Context contextAsUser = phone.getContext().createPackageContextAsUser(
+ phone.getContext().getPackageName(), 0, UserHandle.ALL);
+ contextAsUser.registerReceiver(mBroadcastReceiver, intentFilter,
+ null /* broadcastPermission */, null);
+ } catch (PackageManager.NameNotFoundException e) {
+ loge("Package name not found: " + e.getMessage());
+ }
PhoneConfigurationManager.registerForMultiSimConfigChange(
this, EVENT_BIND_DATA_SERVICE, null);
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
index 381bc6e..ae773bb 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
@@ -187,7 +187,7 @@
DcTracker dct = mPhone.getDcTracker(mTransportType);
if (dct != null) {
Message msg = dct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- status, 0, redirectUrl);
+ status, mDataConnection.getCid(), redirectUrl);
msg.sendToTarget();
}
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index d2354e1..b4500c6 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -66,9 +66,9 @@
import android.provider.Telephony;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.TransportType;
-import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.ApnType;
-import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation.DataFailureCause;
+import android.telephony.Annotation.RilRadioTechnology;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.DataFailCause;
@@ -76,7 +76,6 @@
import android.telephony.PcoData;
import android.telephony.Rlog;
import android.telephony.ServiceState;
-import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
@@ -254,14 +253,6 @@
private static final boolean DATA_STALL_SUSPECTED = true;
private static final boolean DATA_STALL_NOT_SUSPECTED = false;
- private static final String INTENT_RECONNECT_ALARM =
- "com.android.internal.telephony.data-reconnect";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "reconnect_alarm_extra_type";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON =
- "reconnect_alarm_extra_reason";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_TRANSPORT_TYPE =
- "reconnect_alarm_extra_transport_type";
-
private static final String INTENT_DATA_STALL_ALARM =
"com.android.internal.telephony.data-stall";
// Tag for tracking stale alarms
@@ -358,8 +349,6 @@
stopNetStatPoll();
startNetStatPoll();
restartDataStallAlarm();
- } else if (action.startsWith(INTENT_RECONNECT_ALARM)) {
- onActionIntentReconnectAlarm(intent);
} else if (action.equals(INTENT_DATA_STALL_ALARM)) {
onActionIntentDataStallAlarm(intent);
} else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) {
@@ -475,14 +464,6 @@
}
/**
- * Get Tcp Tx/Rx packet count from TrafficStats
- */
- public void updateTcpTxRxSum() {
- this.txPkts = TrafficStats.getMobileTcpTxPackets();
- this.rxPkts = TrafficStats.getMobileTcpRxPackets();
- }
-
- /**
* Get total Tx/Rx packet count from TrafficStats
*/
public void updateTotalTxRxSum() {
@@ -491,28 +472,13 @@
}
}
- private void onActionIntentReconnectAlarm(Intent intent) {
- Message msg = obtainMessage(DctConstants.EVENT_DATA_RECONNECT);
- msg.setData(intent.getExtras());
- sendMessage(msg);
- }
-
- private void onDataReconnect(Bundle bundle) {
- String reason = bundle.getString(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- String apnType = bundle.getString(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
-
+ private void onDataReconnect(ApnContext apnContextforRetry, int subId) {
int phoneSubId = mPhone.getSubId();
- int currSubId = bundle.getInt(PhoneConstants.SUBSCRIPTION_KEY,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ String apnType = apnContextforRetry.getApnType();
+ String reason = apnContextforRetry.getReason();
- // Stop reconnect if not current subId is not correct.
- // FIXME STOPSHIP - phoneSubId is coming up as -1 way after boot and failing this?
- if (!SubscriptionManager.isValidSubscriptionId(currSubId) || (currSubId != phoneSubId)) {
- return;
- }
-
- int transportType = bundle.getInt(INTENT_RECONNECT_ALARM_EXTRA_TRANSPORT_TYPE, 0);
- if (transportType != mTransportType) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId) || (subId != phoneSubId)) {
+ log("onDataReconnect: invalid subId");
return;
}
@@ -540,8 +506,6 @@
}
// TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA???
sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
-
- apnContext.setReconnectIntent(null);
}
}
@@ -652,11 +616,6 @@
//***** Constants
- // Used by puppetmaster/*/radio_stress.py
- private static final String PUPPET_MASTER_RADIO_STRESS_TEST = "gsm.defaultpdpcontext.active";
-
- private static final int POLL_PDP_MILLIS = 5 * 1000;
-
private static final int PROVISIONING_SPINNER_TIMEOUT_MILLIS = 120 * 1000;
static final Uri PREFERAPN_NO_UPDATE_URI_USING_SUBID =
@@ -749,13 +708,6 @@
initApnContexts();
- for (ApnContext apnContext : mApnContexts.values()) {
- // Register the reconnect and restart actions.
- filter = new IntentFilter();
- filter.addAction(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
- mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
- }
-
initEmergencyApnSetting();
addEmergencyApnSetting();
@@ -1753,7 +1705,7 @@
// Make sure reconnection alarm is cleaned up if there is no ApnContext
// associated to the connection.
if (dataConnection != null) {
- cancelReconnectAlarm(apnContext);
+ cancelReconnect(apnContext);
}
str = "cleanUpConnectionInternal: X detach=" + detach + " reason="
+ apnContext.getReason();
@@ -1766,10 +1718,6 @@
*/
@VisibleForTesting
public @NonNull ArrayList<ApnSetting> fetchDunApns() {
- if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)) {
- log("fetchDunApns: net.tethering.noprovisioning=true ret: empty list");
- return new ArrayList<ApnSetting>(0);
- }
int bearer = getDataRat();
ArrayList<ApnSetting> dunCandidates = new ArrayList<ApnSetting>();
ArrayList<ApnSetting> retDunSettings = new ArrayList<ApnSetting>();
@@ -1856,24 +1804,6 @@
return null;
}
- /**
- * Cancels the alarm associated with apnContext.
- *
- * @param apnContext on which the alarm should be stopped.
- */
- private void cancelReconnectAlarm(ApnContext apnContext) {
- if (apnContext == null) return;
-
- PendingIntent intent = apnContext.getReconnectIntent();
-
- if (intent != null) {
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- am.cancel(intent);
- apnContext.setReconnectIntent(null);
- }
- }
-
boolean isPermanentFailure(@DataFailureCause int dcFailCause) {
return (DataFailCause.isPermanentFailure(mPhone.getContext(), dcFailCause,
mPhone.getSubId())
@@ -2198,31 +2128,31 @@
return retry;
}
- private void startAlarmForReconnect(long delay, ApnContext apnContext) {
- String apnType = apnContext.getApnType();
-
- Intent intent = new Intent(INTENT_RECONNECT_ALARM + "." + apnType);
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnType);
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TRANSPORT_TYPE, mTransportType);
- SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ private void startReconnect(long delay, ApnContext apnContext) {
+ Message msg = obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
+ mPhone.getSubId(), mTransportType, apnContext);
+ cancelReconnect(apnContext);
+ sendMessageDelayed(msg, delay);
if (DBG) {
- log("startAlarmForReconnect: delay=" + delay + " action=" + intent.getAction()
- + " apn=" + apnContext);
+ log("startReconnect: delay=" + delay + " apn="
+ + apnContext + "reason: " + apnContext.getReason()
+ + " subId: " + mPhone.getSubId());
}
+ }
- PendingIntent alarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0,
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
- apnContext.setReconnectIntent(alarmIntent);
+ /**
+ * Cancels the alarm associated with apnContext.
+ *
+ * @param apnContext on which the alarm should be stopped.
+ */
+ private void cancelReconnect(ApnContext apnContext) {
+ if (apnContext == null) return;
- // Use the exact timer instead of the inexact one to provide better user experience.
- // In some extreme cases, we saw the retry was delayed for few minutes.
- // Note that if the stated trigger time is in the past, the alarm will be triggered
- // immediately.
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + delay, alarmIntent);
+ if (DBG) {
+ log("cancelReconnect: apn=" + apnContext);
+ }
+ removeMessages(DctConstants.EVENT_DATA_RECONNECT, apnContext);
}
private void notifyNoData(@DataFailureCause int lastFailCauseCode,
@@ -2759,24 +2689,12 @@
}
// everything is setup
- if (TextUtils.equals(apnContext.getApnType(), PhoneConstants.APN_TYPE_DEFAULT)) {
- try {
- SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "true");
- } catch (RuntimeException ex) {
- log("Failed to set PUPPET_MASTER_RADIO_STRESS_TEST to true");
- }
- if (mCanSetPreferApn && mPreferredApn == null) {
- if (DBG) log("onDataSetupComplete: PREFERRED APN is null");
- mPreferredApn = apn;
- if (mPreferredApn != null) {
- setPreferredApn(mPreferredApn.getId());
- }
- }
- } else {
- try {
- SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "false");
- } catch (RuntimeException ex) {
- log("Failed to set PUPPET_MASTER_RADIO_STRESS_TEST to false");
+ if (TextUtils.equals(apnContext.getApnType(), PhoneConstants.APN_TYPE_DEFAULT)
+ && mCanSetPreferApn && mPreferredApn == null) {
+ if (DBG) log("onDataSetupComplete: PREFERRED APN is null");
+ mPreferredApn = apn;
+ if (mPreferredApn != null) {
+ setPreferredApn(mPreferredApn.getId());
}
}
@@ -2786,7 +2704,8 @@
checkDataRoamingStatus(false);
boolean isProvApn = apnContext.isProvisioningApn();
- final ConnectivityManager cm = ConnectivityManager.from(mPhone.getContext());
+ final ConnectivityManager cm = (ConnectivityManager) mPhone.getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
if (mProvisionBroadcastReceiver != null) {
mPhone.getContext().unregisterReceiver(mProvisionBroadcastReceiver);
mProvisionBroadcastReceiver = null;
@@ -2903,7 +2822,7 @@
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel
- startAlarmForReconnect(delay, apnContext);
+ startReconnect(delay, apnContext);
} else {
// If we are not going to retry any APN, set this APN context to failed state.
// This would be the final state of a data connection.
@@ -2920,10 +2839,11 @@
*
* @param status One of {@code NetworkAgent.VALID_NETWORK} or
* {@code NetworkAgent.INVALID_NETWORK}.
+ * @param cid context id {@code cid}
* @param redirectUrl If the Internet probe was redirected, this
* is the destination it was redirected to, otherwise {@code null}
*/
- private void onNetworkStatusChanged(int status, String redirectUrl) {
+ private void onNetworkStatusChanged(int status, int cid, String redirectUrl) {
if (!TextUtils.isEmpty(redirectUrl)) {
Intent intent = new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED);
intent.putExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY, redirectUrl);
@@ -2931,6 +2851,7 @@
log("Notify carrier signal receivers with redirectUrl: " + redirectUrl);
} else {
final boolean isValid = status == NetworkAgent.VALID_NETWORK;
+ final DataConnection dc = getDataConnectionByContextId(cid);
if (!mDsRecoveryHandler.isRecoveryOnBadNetworkEnabled()) {
if (DBG) log("Skip data stall recovery on network status change with in threshold");
return;
@@ -2939,7 +2860,9 @@
if (DBG) log("Skip data stall recovery on non WWAN");
return;
}
- mDsRecoveryHandler.processNetworkStatusChanged(isValid);
+ if (dc != null && dc.isValidationRequired()) {
+ mDsRecoveryHandler.processNetworkStatusChanged(isValid);
+ }
}
}
@@ -2983,11 +2906,6 @@
}
// If APN is still enabled, try to bring it back up automatically
if (mAttached.get() && apnContext.isReady() && retryAfterDisconnected(apnContext)) {
- try {
- SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "false");
- } catch (RuntimeException ex) {
- log("Failed to set PUPPET_MASTER_RADIO_STRESS_TEST to false");
- }
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel.
// This also helps in any external dependency to turn off the context.
@@ -2996,7 +2914,7 @@
if (delay > 0) {
// Data connection is in IDLE state, so when we reconnect later, we'll rebuild
// the waiting APN list, which will also reset/reconfigure the retry manager.
- startAlarmForReconnect(delay, apnContext);
+ startReconnect(delay, apnContext);
}
} else {
boolean restartRadioAfterProvisioning = mPhone.getContext().getResources().getBoolean(
@@ -3291,16 +3209,11 @@
apnList = sortApnListByPreferred(apnList);
if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
return apnList;
- } else {
- if (DBG) log("buildWaitingApns: no preferred APN");
- setPreferredApn(-1);
- mPreferredApn = null;
}
- } else {
- if (DBG) log("buildWaitingApns: no preferred APN");
- setPreferredApn(-1);
- mPreferredApn = null;
}
+ if (DBG) log("buildWaitingApns: no preferred APN");
+ setPreferredApn(-1);
+ mPreferredApn = null;
}
if (DBG) log("buildWaitingApns: mAllApnSettings=" + mAllApnSettings);
@@ -3588,8 +3501,9 @@
case DctConstants.EVENT_NETWORK_STATUS_CHANGED:
int status = msg.arg1;
+ int cid = msg.arg2;
String url = (String) msg.obj;
- onNetworkStatusChanged(status, url);
+ onNetworkStatusChanged(status, cid, url);
break;
case DctConstants.EVENT_RADIO_AVAILABLE:
@@ -3780,7 +3694,8 @@
break;
}
case DctConstants.EVENT_DATA_RECONNECT:
- onDataReconnect(msg.getData());
+ if (DBG) log("EVENT_DATA_RECONNECT: subId=" + msg.arg1);
+ onDataReconnect((ApnContext) msg.obj, msg.arg1);
break;
case DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED:
onDataServiceBindingChanged((Boolean) ((AsyncResult) msg.obj).result);
@@ -4190,19 +4105,20 @@
return;
}
for (ApnContext apnContext : mApnContexts.values()) {
- ArrayList<ApnSetting> currentWaitingApns = apnContext.getWaitingApns();
- ArrayList<ApnSetting> waitingApns = buildWaitingApns(
- apnContext.getApnType(), getDataRat());
- if (VDBG) log("new waitingApns:" + waitingApns);
- if ((currentWaitingApns != null)
- && ((waitingApns.size() != currentWaitingApns.size())
- // Check if the existing waiting APN list can cover the newly built APN
- // list. If yes, then we don't need to tear down the existing data call.
- // TODO: We probably need to rebuild APN list when roaming status changes.
- || !containsAllApns(currentWaitingApns, waitingApns))) {
- if (VDBG) log("new waiting apn is different for " + apnContext);
- apnContext.setWaitingApns(waitingApns);
- if (!apnContext.isDisconnected()) {
+ if (!apnContext.isDisconnected()) {
+ ArrayList<ApnSetting> currentWaitingApns = apnContext.getWaitingApns();
+ ArrayList<ApnSetting> waitingApns = buildWaitingApns(
+ apnContext.getApnType(), getDataRat());
+ if (VDBG) log("new waitingApns:" + waitingApns);
+ if ((currentWaitingApns != null)
+ && ((waitingApns.size() != currentWaitingApns.size())
+ // Check if the existing waiting APN list can cover the newly built APN
+ // list. If yes, then we don't need to tear down the existing data call.
+ // TODO: We probably need to rebuild APN list when roaming status
+ // changes.
+ || !containsAllApns(currentWaitingApns, waitingApns))) {
+ if (VDBG) log("new waiting apn is different for " + apnContext);
+ apnContext.setWaitingApns(waitingApns);
if (VDBG) log("cleanUpConnectionsOnUpdatedApns for " + apnContext);
apnContext.setReason(reason);
cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext);
@@ -4577,7 +4493,7 @@
long sent, received;
TxRxSum preTxRxSum = new TxRxSum(mDataStallTxRxSum);
- mDataStallTxRxSum.updateTcpTxRxSum();
+ mDataStallTxRxSum.updateTotalTxRxSum();
if (VDBG_STALL) {
log("updateDataStallInfo: mDataStallTxRxSum=" + mDataStallTxRxSum +
diff --git a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
index fa9723a..f391320 100644
--- a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
@@ -30,13 +30,14 @@
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation.ApnType;
import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
import android.telephony.data.ApnSetting;
import android.util.LocalLog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneSwitcher;
import com.android.internal.telephony.SubscriptionController;
-import com.android.internal.telephony.SubscriptionMonitor;
import com.android.internal.telephony.dataconnection.DcTracker.ReleaseNetworkType;
import com.android.internal.telephony.dataconnection.DcTracker.RequestNetworkType;
import com.android.internal.telephony.dataconnection.TransportManager.HandoverParams;
@@ -59,8 +60,10 @@
private static final int TELEPHONY_NETWORK_SCORE = 50;
- private static final int EVENT_ACTIVE_PHONE_SWITCH = 1;
- private static final int EVENT_SUBSCRIPTION_CHANGED = 2;
+ @VisibleForTesting
+ public static final int EVENT_ACTIVE_PHONE_SWITCH = 1;
+ @VisibleForTesting
+ public static final int EVENT_SUBSCRIPTION_CHANGED = 2;
private static final int EVENT_NETWORK_REQUEST = 3;
private static final int EVENT_NETWORK_RELEASE = 4;
private static final int EVENT_DATA_HANDOVER_NEEDED = 5;
@@ -68,7 +71,6 @@
private final PhoneSwitcher mPhoneSwitcher;
private final SubscriptionController mSubscriptionController;
- private final SubscriptionMonitor mSubscriptionMonitor;
private final LocalLog mLocalLog = new LocalLog(REQUEST_LOG_SIZE);
// Key: network request. Value: the transport of DcTracker it applies to,
@@ -83,11 +85,11 @@
private int mSubscriptionId;
- private final Handler mInternalHandler;
+ @VisibleForTesting
+ public final Handler mInternalHandler;
- public TelephonyNetworkFactory(SubscriptionMonitor subscriptionMonitor, Looper looper,
- Phone phone) {
+ public TelephonyNetworkFactory(Looper looper, Phone phone) {
super(looper, phone.getContext(), "TelephonyNetworkFactory[" + phone.getPhoneId()
+ "]", null);
mPhone = phone;
@@ -100,7 +102,6 @@
setScoreFilter(TELEPHONY_NETWORK_SCORE);
mPhoneSwitcher = PhoneSwitcher.getInstance();
- mSubscriptionMonitor = subscriptionMonitor;
LOG_TAG = "TelephonyNetworkFactory[" + mPhone.getPhoneId() + "]";
mPhoneSwitcher.registerForActivePhoneSwitch(mInternalHandler, EVENT_ACTIVE_PHONE_SWITCH,
@@ -109,12 +110,20 @@
EVENT_DATA_HANDOVER_NEEDED);
mSubscriptionId = INVALID_SUBSCRIPTION_ID;
- mSubscriptionMonitor.registerForSubscriptionChanged(mPhone.getPhoneId(), mInternalHandler,
- EVENT_SUBSCRIPTION_CHANGED, null);
+ SubscriptionManager.from(mPhone.getContext()).addOnSubscriptionsChangedListener(
+ mSubscriptionsChangedListener);
register();
}
+ private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ mInternalHandler.sendEmptyMessage(EVENT_SUBSCRIPTION_CHANGED);
+ }
+ };
+
private NetworkCapabilities makeNetworkFilter(SubscriptionController subscriptionController,
int phoneId) {
final int subscriptionId = subscriptionController.getSubIdUsingPhoneId(phoneId);
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index af2c61b..a0feb80 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -75,7 +75,8 @@
private static final String EMERGENCY_NUMBER_DB_OTA_FILE_NAME = "emergency_number_db";
private static final String EMERGENCY_NUMBER_DB_OTA_FILE_PATH =
"misc/emergencynumberdb/" + EMERGENCY_NUMBER_DB_OTA_FILE_NAME;
-
+ private File mEmergencyNumberDbOtaFilePath = new File(Environment.getDataDirectory(),
+ EMERGENCY_NUMBER_DB_OTA_FILE_PATH);
/** @hide */
public static boolean DBG = false;
@@ -124,6 +125,8 @@
private static final int EVENT_UPDATE_EMERGENCY_NUMBER_PREFIX = 4;
/** Event indicating the update for the OTA emergency number database. */
private static final int EVENT_UPDATE_OTA_EMERGENCY_NUMBER_DB = 5;
+ /** Event indicating the override for the test OTA emergency number database. */
+ private static final int EVENT_OVERRIDE_TEST_OTA_EMERGENCY_NUMBER_DB_FILE_PATH = 6;
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
@@ -153,11 +156,6 @@
updateEmergencyCountryIsoAllPhones(countryIso);
}
return;
- } else if (intent.getAction().equals(
- TelephonyManager.ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED)) {
- logd("ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED: triggered");
- updateOtaEmergencyNumberDatabase();
- return;
}
}
};
@@ -183,8 +181,6 @@
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
// Receive Telephony Network Country Changes
filter.addAction(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED);
- // Receive Emergency Number OTA Update Changes
- filter.addAction(TelephonyManager.ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED);
mPhone.getContext().registerReceiver(mIntentReceiver, filter);
} else {
@@ -225,7 +221,7 @@
}
break;
case EVENT_UPDATE_EMERGENCY_NUMBER_TEST_MODE:
- if (msg.obj == null) {
+ if (msg.obj == null && msg.arg1 != RESET_EMERGENCY_NUMBER_TEST_MODE) {
loge("EVENT_UPDATE_EMERGENCY_NUMBER_TEST_MODE: Result from"
+ " executeEmergencyNumberTestModeCommand is null.");
} else {
@@ -244,6 +240,14 @@
case EVENT_UPDATE_OTA_EMERGENCY_NUMBER_DB:
updateOtaEmergencyNumberListDatabaseAndNotify();
break;
+ case EVENT_OVERRIDE_TEST_OTA_EMERGENCY_NUMBER_DB_FILE_PATH:
+ if (msg.obj == null) {
+ loge("EVENT_OVERRIDE_TEST_OTA_EMERGENCY_NUMBER_DB_FILE_PATH:"
+ + " Result from otaFilePath is null.");
+ } else {
+ overrideTestOtaEmergencyNumberDbFilePath((String) msg.obj);
+ }
+ break;
}
}
@@ -341,6 +345,16 @@
this.obtainMessage(EVENT_UPDATE_OTA_EMERGENCY_NUMBER_DB).sendToTarget();
}
+ /**
+ * Override the test OTA Emergency Number database file path.
+ *
+ * @hide
+ */
+ public void updateTestOtaEmergencyNumberDbFilePath(String otaFilePath) {
+ this.obtainMessage(
+ EVENT_OVERRIDE_TEST_OTA_EMERGENCY_NUMBER_DB_FILE_PATH, otaFilePath).sendToTarget();
+ }
+
private EmergencyNumber convertEmergencyNumberFromEccInfo(EccInfo eccInfo, String countryIso) {
String phoneNumber = eccInfo.phoneNumber.trim();
if (phoneNumber.isEmpty()) {
@@ -441,8 +455,7 @@
List<EmergencyNumber> updatedOtaEmergencyNumberList = new ArrayList<>();
try {
inputStream = new BufferedInputStream(
- new FileInputStream(new File(Environment.getDataDirectory(),
- EMERGENCY_NUMBER_DB_OTA_FILE_PATH)));
+ new FileInputStream(mEmergencyNumberDbOtaFilePath));
allEccMessages = ProtobufEccData.AllInfo.parseFrom(readInputStreamToByteArray(
new GZIPInputStream(inputStream)));
logd(mCountryIso + " ota emergency database is loaded. Ver: " + otaDatabaseVersion);
@@ -539,6 +552,26 @@
notifyEmergencyNumberList();
}
+ private void overrideTestOtaEmergencyNumberDbFilePath(String otaFilePath) {
+ logd("overrideTestOtaEmergencyNumberDbFilePath:" + otaFilePath);
+ if (otaFilePath.equals("RESET")) {
+ mEmergencyNumberDbOtaFilePath = new File(Environment.getDataDirectory(),
+ EMERGENCY_NUMBER_DB_OTA_FILE_PATH);
+ return;
+ }
+ String[] otaFilePathParts = otaFilePath.split("@");
+ if (otaFilePathParts.length != 2) {
+ loge("overrideTestOtaEmergencyNumberDbFilePath: otaFilePath length error");
+ return;
+ }
+ if (otaFilePathParts[0].equals("sdcard")) {
+ mEmergencyNumberDbOtaFilePath = new File(
+ Environment.getExternalStorageDirectory(), otaFilePathParts[1]);
+ } else {
+ loge("overrideTestOtaEmergencyNumberDbFilePath: otaFilePath prefix error");
+ }
+ }
+
private void updateOtaEmergencyNumberListDatabaseAndNotify() {
logd("updateOtaEmergencyNumberListDatabaseAndNotify():"
+ " receiving Emegency Number database OTA update");
@@ -724,6 +757,10 @@
return mCountryIso;
}
+ public int getEmergencyNumberDbVersion() {
+ return mCurrentDatabaseVersion;
+ }
+
private synchronized void updateEmergencyCountryIso(String countryIso) {
mCountryIso = countryIso;
}
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index 7c69cfb..694db12 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -1228,7 +1228,8 @@
final PackageInfo info;
try {
- info = mPackageManager.getPackageInfo(callingPackage, PackageManager.GET_SIGNATURES);
+ info = mPackageManager.getPackageInfo(callingPackage,
+ PackageManager.GET_SIGNING_CERTIFICATES);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Calling package valid but gone");
return false;
diff --git a/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java b/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
index 052d89c..1494480 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmCellBroadcastHandler.java
@@ -26,6 +26,7 @@
import android.os.AsyncResult;
import android.os.Message;
import android.provider.Telephony.CellBroadcasts;
+import android.telephony.CbGeoUtils.Geometry;
import android.telephony.CellLocation;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
@@ -33,7 +34,6 @@
import android.telephony.gsm.GsmCellLocation;
import android.text.format.DateUtils;
-import com.android.internal.telephony.CbGeoUtils.Geometry;
import com.android.internal.telephony.CellBroadcastHandler;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage;
@@ -138,7 +138,7 @@
// cell broadcasts.
int maximumWaitTimeSec = 0;
for (SmsCbMessage msg : cbMessages) {
- maximumWaitTimeSec = Math.max(maximumWaitTimeSec, msg.getMaximumWaitingTime());
+ maximumWaitTimeSec = Math.max(maximumWaitTimeSec, msg.getMaximumWaitingDuration());
}
if (DBG) {
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index 2c3ed6d..a8cc125 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -539,7 +539,6 @@
context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter,
null,
null);
-
context.registerReceiver(mConfigChangedReceiver, new IntentFilter(
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
context.registerReceiver(mBootCompleted, new IntentFilter(
@@ -1363,7 +1362,7 @@
for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
serviceIntent,
PackageManager.GET_META_DATA,
- UserHandle.getUserHandleForUid(mContext.getUserId()))) {
+ UserHandle.getUserHandleForUid(UserHandle.myUserId()))) {
ServiceInfo serviceInfo = entry.serviceInfo;
if (serviceInfo != null) {
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index af26eba..c4b7399 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -27,6 +27,7 @@
import android.os.IInterface;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
@@ -639,7 +640,7 @@
try {
if (mPackageManager != null) {
mPackageManager.grantDefaultPermissionsToEnabledImsServices(pkgToGrant,
- mContext.getUserId());
+ UserHandle.myUserId());
}
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unable to grant permissions, binder died.");
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 7a863d0..7f2e70d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -24,6 +24,7 @@
import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_ALL;
import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MO;
import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BA_MT;
+import static com.android.internal.telephony.CommandsInterface.CB_FACILITY_BIC_ACR;
import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
@@ -46,6 +47,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.net.NetworkStats;
import android.net.Uri;
import android.os.AsyncResult;
@@ -203,7 +205,10 @@
private ServiceState mSS = new ServiceState();
private RcsFeatureManager mRcsManager;
- private final FeatureConnector<RcsFeatureManager> mRcsManagerConnector;
+ @VisibleForTesting
+ public FeatureConnector<RcsFeatureManager> mRcsManagerConnector;
+ @VisibleForTesting
+ public FeatureConnector.Listener<RcsFeatureManager> mRcsFeatureConnectorListener;
// To redial silently through GSM or CDMA when dialing through IMS fails
private String mLastDialString;
@@ -255,6 +260,11 @@
}
@Override
+ public int getEmergencyNumberDbVersion() {
+ return getEmergencyNumberTracker().getEmergencyNumberDbVersion();
+ }
+
+ @Override
public EmergencyNumberTracker getEmergencyNumberTracker() {
return mDefaultPhone.getEmergencyNumberTracker();
}
@@ -330,34 +340,9 @@
// Force initial roaming state update later, on EVENT_CARRIER_CONFIG_CHANGED.
// Settings provider or CarrierConfig may not be loaded now.
- mRcsManagerConnector = new FeatureConnector<RcsFeatureManager>(mContext, mPhoneId,
- new FeatureConnector.Listener<RcsFeatureManager>() {
- @Override
- public boolean isSupported() {
- if (!ImsManager.isImsSupportedOnDevice(mContext)) {
- return false;
- }
- if (!RcsFeatureManager.isRcsUceSupportedByCarrier(mContext, mPhoneId)) {
- return false;
- }
- return true;
- }
-
- @Override
- public RcsFeatureManager getFeatureManager() {
- return new RcsFeatureManager(mContext, mPhoneId);
- }
-
- @Override
- public void connectionReady(RcsFeatureManager manager) throws ImsException {
- mRcsManager = manager;
- }
-
- @Override
- public void connectionUnavailable() {
- }
- }, mContext.getMainExecutor(), "ImsPhone");
- mRcsManagerConnector.connect();
+ // Listen to the carrier config changed to initialize RcsFeatureManager
+ IntentFilter filter = new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ mContext.registerReceiver(mCarrierConfigChangedReceiver, filter);
}
//todo: get rid of this function. It is not needed since parentPhone obj never changes
@@ -381,7 +366,75 @@
mDefaultPhone.unregisterForServiceStateChanged(this);
}
- mRcsManagerConnector.disconnect();
+ mContext.unregisterReceiver(mCarrierConfigChangedReceiver);
+
+ if (mRcsManagerConnector != null) {
+ mRcsManagerConnector.disconnect();
+ mRcsManagerConnector = null;
+ }
+ }
+
+ private BroadcastReceiver mCarrierConfigChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null) {
+ return;
+ }
+ if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
+ Bundle bundle = intent.getExtras();
+ if (bundle == null) {
+ return;
+ }
+ int phoneId = bundle.getInt(CarrierConfigManager.EXTRA_SLOT_INDEX);
+ if (phoneId == mPhoneId) {
+ sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
+ }
+ }
+ }
+ };
+
+ /**
+ * Create RcsManagerConnector to initialize RcsFeatureManager
+ */
+ @VisibleForTesting
+ public void initRcsFeatureManager() {
+ if (mRcsManagerConnector != null) {
+ mRcsManagerConnector.disconnect();
+ mRcsManagerConnector = null;
+ }
+
+ logd("initRcsFeatureManager");
+ mRcsFeatureConnectorListener = new FeatureConnector.Listener<>() {
+ @Override
+ public boolean isSupported() {
+ // Check if Telephony IMS is supported or not
+ if (!ImsManager.isImsSupportedOnDevice(mContext)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public RcsFeatureManager getFeatureManager() {
+ return new RcsFeatureManager(mContext, mPhoneId);
+ }
+
+ @Override
+ public void connectionReady(RcsFeatureManager manager) throws ImsException {
+ logd("RcsFeatureManager is ready");
+ mRcsManager = manager;
+ }
+
+ @Override
+ public void connectionUnavailable() {
+ logd("RcsFeatureManager is unavailable");
+ mRcsManager = null;
+ }
+ };
+
+ mRcsManagerConnector = new FeatureConnector<>(mContext, mPhoneId,
+ mRcsFeatureConnectorListener, mContext.getMainExecutor(), LOG_TAG);
+ mRcsManagerConnector.connect();
}
@UnsupportedAppUsage
@@ -1128,6 +1181,8 @@
return ImsUtInterface.CB_BA_MO;
} else if (CB_FACILITY_BA_MT.equals(facility)) {
return ImsUtInterface.CB_BA_MT;
+ } else if (CB_FACILITY_BIC_ACR.equals(facility)) {
+ return ImsUtInterface.CB_BIC_ACR;
}
return 0;
@@ -1588,6 +1643,12 @@
updateRoamingState(sst.mSS);
}
break;
+ case EVENT_CARRIER_CONFIG_CHANGED:
+ if (DBG) logd("EVENT_CARRIER_CONFIG_CHANGED");
+ if (mRcsManager == null) {
+ initRcsFeatureManager();
+ }
+ break;
default:
super.handleMessage(msg);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 0070e3d..0fbc3d4 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -912,6 +912,7 @@
mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
pendingCallClirMode = clirMode;
mPendingCallVideoState = videoState;
+ mPendingIntentExtras = dialArgs.intentExtras;
pendingCallInEcm = true;
}
}
@@ -2793,8 +2794,8 @@
}
foregroundImsPhoneCall.merge(peerImsPhoneCall, ImsPhoneCall.State.ACTIVE);
+ final ImsPhoneConnection conn = findConnection(call);
try {
- final ImsPhoneConnection conn = findConnection(call);
log("onCallMerged: ImsPhoneConnection=" + conn);
log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
setVideoCallProvider(conn, call);
@@ -2822,6 +2823,11 @@
// Reset the flag.
call.resetIsMergeRequestedByConf(false);
}
+
+ // Notify completion of merge
+ if (conn != null) {
+ conn.handleMergeComplete();
+ }
logState();
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 403b535..49b1f2f 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -1010,7 +1010,7 @@
}
} else if (mSc != null && mSc.equals(SC_WAIT)) {
// sia = basic service group
- int serviceClass = siToServiceClass(mSib);
+ int serviceClass = siToServiceClass(mSia);
if (isActivate() || isDeactivate()) {
mPhone.setCallWaiting(isActivate(), serviceClass,
diff --git a/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java b/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
index aef2535..27d23e3 100644
--- a/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/NewNitzStateMachineImpl.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
import android.content.Context;
import android.telephony.Rlog;
import android.util.TimestampedValue;
@@ -28,7 +29,6 @@
import com.android.internal.telephony.NitzStateMachine;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TimeZoneLookupHelper;
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion;
import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
@@ -100,8 +100,6 @@
// Miscellaneous dependencies and helpers not related to detection state.
private final int mPhoneId;
- /** Accesses global information about the device. */
- private final DeviceState mDeviceState;
/** Applied to NITZ signals during input filtering. */
private final NitzSignalInputFilterPredicate mNitzSignalInputFilter;
/** Creates {@link PhoneTimeZoneSuggestion} for passing to the time zone detection service. */
@@ -122,13 +120,11 @@
// Time Zone detection state.
/**
- * Records whether the device should have a country code available via
- * {@link DeviceState#getNetworkCountryIsoForPhone()}. Before this an NITZ signal
- * received is (almost always) not enough to determine time zone. On test networks the country
- * code should be available but can still be an empty string but this flag indicates that the
- * information available is unlikely to improve.
+ * Records the country to use for time zone detection. It can be a valid ISO 3166 alpha-2 code
+ * (lower case), empty (test network) or null (no country detected). A country code is required
+ * to determine time zone except when on a test network.
*/
- private boolean mGotCountryCode = false;
+ private String mCountryIsoCode;
/**
* Creates an instance for the supplied {@link Phone}.
@@ -145,7 +141,7 @@
NitzSignalInputFilterPredicate nitzSignalFilter =
NitzSignalInputFilterPredicateFactory.create(phone.getContext(), deviceState);
return new NewNitzStateMachineImpl(
- phoneId, nitzSignalFilter, timeZoneSuggester, newTimeServiceHelper, deviceState);
+ phoneId, nitzSignalFilter, timeZoneSuggester, newTimeServiceHelper);
}
/**
@@ -156,11 +152,10 @@
public NewNitzStateMachineImpl(int phoneId,
@NonNull NitzSignalInputFilterPredicate nitzSignalInputFilter,
@NonNull TimeZoneSuggester timeZoneSuggester,
- @NonNull NewTimeServiceHelper newTimeServiceHelper, @NonNull DeviceState deviceState) {
+ @NonNull NewTimeServiceHelper newTimeServiceHelper) {
mPhoneId = phoneId;
mTimeZoneSuggester = Objects.requireNonNull(timeZoneSuggester);
mNewTimeServiceHelper = Objects.requireNonNull(newTimeServiceHelper);
- mDeviceState = Objects.requireNonNull(deviceState);
mNitzSignalInputFilter = Objects.requireNonNull(nitzSignalInputFilter);
}
@@ -177,17 +172,26 @@
}
private void clearNetworkStateAndRerunDetection(String reason) {
- // Assume any previous NITZ signals received are now invalid.
+ if (mLatestNitzSignal == null) {
+ // The network state is already empty so there's no need to do anything.
+ if (DBG) {
+ Rlog.d(LOG_TAG, reason + ": mLatestNitzSignal was already null. Nothing to do.");
+ }
+ return;
+ }
+
+ // The previous NITZ signal received is now invalid so clear it.
mLatestNitzSignal = null;
- String countryIsoCode =
- mGotCountryCode ? mDeviceState.getNetworkCountryIsoForPhone() : null;
-
+ // countryIsoCode can be assigned null here, in which case the doTimeZoneDetection() call
+ // below will do nothing, which is ok as nothing will have changed.
+ String countryIsoCode = mCountryIsoCode;
if (DBG) {
Rlog.d(LOG_TAG, reason + ": countryIsoCode=" + countryIsoCode);
}
- // Generate a new time zone suggestion and update the service as needed.
+ // Generate a new time zone suggestion (which could be an empty suggestion) and update the
+ // service as needed.
doTimeZoneDetection(countryIsoCode, null /* nitzSignal */, reason);
// Generate a new time suggestion and update the service as needed.
@@ -195,30 +199,32 @@
}
@Override
- public void handleNetworkCountryCodeSet(boolean countryChanged) {
+ public void handleCountryDetected(@NonNull String countryIsoCode) {
if (DBG) {
- Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: countryChanged=" + countryChanged
+ Rlog.d(LOG_TAG, "handleCountryDetected: countryIsoCode=" + countryIsoCode
+ ", mLatestNitzSignal=" + mLatestNitzSignal);
}
- mGotCountryCode = true;
- // Generate a new time zone suggestion and update the service as needed.
- String countryIsoCode = mDeviceState.getNetworkCountryIsoForPhone();
- doTimeZoneDetection(countryIsoCode, mLatestNitzSignal,
- "handleNetworkCountryCodeSet(" + countryChanged + ")");
+ String oldCountryIsoCode = mCountryIsoCode;
+ mCountryIsoCode = Objects.requireNonNull(countryIsoCode);
+ if (!Objects.equals(oldCountryIsoCode, mCountryIsoCode)) {
+ // Generate a new time zone suggestion and update the service as needed.
+ doTimeZoneDetection(countryIsoCode, mLatestNitzSignal,
+ "handleCountryDetected(\"" + countryIsoCode + "\")");
+ }
}
@Override
- public void handleNetworkCountryCodeUnavailable() {
+ public void handleCountryUnavailable() {
if (DBG) {
- Rlog.d(LOG_TAG, "handleNetworkCountryCodeUnavailable:"
+ Rlog.d(LOG_TAG, "handleCountryUnavailable:"
+ " mLatestNitzSignal=" + mLatestNitzSignal);
}
- mGotCountryCode = false;
+ mCountryIsoCode = null;
// Generate a new time zone suggestion and update the service as needed.
doTimeZoneDetection(null /* countryIsoCode */, mLatestNitzSignal,
- "handleNetworkCountryCodeUnavailable()");
+ "handleCountryUnavailable()");
}
@Override
@@ -240,8 +246,7 @@
String reason = "handleNitzReceived(" + nitzSignal + ")";
// Generate a new time zone suggestion and update the service as needed.
- String countryIsoCode =
- mGotCountryCode ? mDeviceState.getNetworkCountryIsoForPhone() : null;
+ String countryIsoCode = mCountryIsoCode;
doTimeZoneDetection(countryIsoCode, nitzSignal, reason);
// Generate a new time suggestion and update the service as needed.
@@ -263,8 +268,8 @@
// will be made after airplane mode is re-enabled as the device re-establishes network
// connectivity.
- // Clear time zone detection state.
- mGotCountryCode = false;
+ // Clear country detection state.
+ mCountryIsoCode = null;
String reason = "handleAirplaneModeChanged(" + on + ")";
clearNetworkStateAndRerunDetection(reason);
@@ -282,6 +287,7 @@
PhoneTimeZoneSuggestion suggestion =
mTimeZoneSuggester.getTimeZoneSuggestion(mPhoneId, countryIsoCode, nitzSignal);
suggestion.addDebugInfo("Detection reason=" + reason);
+
if (DBG) {
Rlog.d(LOG_TAG, "doTimeZoneDetection: countryIsoCode=" + countryIsoCode
+ ", nitzSignal=" + nitzSignal + ", suggestion=" + suggestion
@@ -305,22 +311,20 @@
@NonNull String reason) {
try {
Objects.requireNonNull(reason);
+
+ PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhoneId);
if (nitzSignal == null) {
- // Do nothing to withdraw previous suggestions: the service currently does not
- // support withdrawing suggestions.
- return;
+ timeSuggestion.addDebugInfo("Clearing time zone suggestion"
+ + " reason=" + reason);
+ } else {
+ TimestampedValue<Long> newNitzTime = new TimestampedValue<>(
+ nitzSignal.getReferenceTimeMillis(),
+ nitzSignal.getValue().getCurrentTimeInMillis());
+ timeSuggestion.setUtcTime(newNitzTime);
+ timeSuggestion.addDebugInfo("Sending new time zone suggestion"
+ + " nitzSignal=" + nitzSignal
+ + ", reason=" + reason);
}
-
- Objects.requireNonNull(nitzSignal.getValue());
-
- TimestampedValue<Long> newNitzTime = new TimestampedValue<>(
- nitzSignal.getReferenceTimeMillis(),
- nitzSignal.getValue().getCurrentTimeInMillis());
- PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhoneId, newNitzTime);
- timeSuggestion.addDebugInfo("doTimeDetection: NITZ signal used"
- + " nitzSignal=" + nitzSignal
- + ", newNitzTime=" + newNitzTime
- + ", reason=" + reason);
mNewTimeServiceHelper.suggestDeviceTime(timeSuggestion);
} catch (RuntimeException ex) {
Rlog.e(LOG_TAG, "doTimeDetection: Exception thrown"
@@ -334,7 +338,7 @@
@Override
public void dumpState(PrintWriter pw) {
pw.println(" NewNitzStateMachineImpl.mLatestNitzSignal=" + mLatestNitzSignal);
- pw.println(" NewNitzStateMachineImpl.mGotCountryCode=" + mGotCountryCode);
+ pw.println(" NewNitzStateMachineImpl.mCountryIsoCode=" + mCountryIsoCode);
mNewTimeServiceHelper.dumpState(pw);
pw.flush();
}
diff --git a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java
index 7984c97..bc3a726 100644
--- a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java
+++ b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelper.java
@@ -19,8 +19,8 @@
import android.annotation.NonNull;
import android.app.timedetector.PhoneTimeSuggestion;
import android.app.timedetector.TimeDetector;
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion;
import com.android.internal.util.IndentingPrintWriter;
import java.io.PrintWriter;
diff --git a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
index 337423b..36d38f6 100644
--- a/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/NewTimeServiceHelperImpl.java
@@ -20,14 +20,14 @@
import android.annotation.Nullable;
import android.app.timedetector.PhoneTimeSuggestion;
import android.app.timedetector.TimeDetector;
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
+import android.app.timezonedetector.TimeZoneDetector;
import android.content.Context;
import android.util.LocalLog;
import android.util.TimestampedValue;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.metrics.TelephonyMetrics;
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion;
-import com.android.internal.telephony.nitz.service.TimeZoneDetectionService;
import com.android.internal.util.IndentingPrintWriter;
import java.io.PrintWriter;
@@ -40,7 +40,7 @@
private final int mPhoneId;
private final TimeDetector mTimeDetector;
- private final TimeZoneDetectionService mTimeZoneDetector;
+ private final TimeZoneDetector mTimeZoneDetector;
private final LocalLog mTimeZoneLog = new LocalLog(30);
private final LocalLog mTimeLog = new LocalLog(30);
@@ -57,18 +57,20 @@
mPhoneId = phone.getPhoneId();
Context context = Objects.requireNonNull(phone.getContext());
mTimeDetector = Objects.requireNonNull(context.getSystemService(TimeDetector.class));
- mTimeZoneDetector = Objects.requireNonNull(TimeZoneDetectionService.getInstance(context));
+ mTimeZoneDetector =
+ Objects.requireNonNull(context.getSystemService(TimeZoneDetector.class));
}
@Override
public void suggestDeviceTime(@NonNull PhoneTimeSuggestion phoneTimeSuggestion) {
- mTimeLog.log("Suggesting system clock update: " + phoneTimeSuggestion);
+ mTimeLog.log("Sending time suggestion: " + phoneTimeSuggestion);
- // 3 nullness assertions in 1 line
- Objects.requireNonNull(phoneTimeSuggestion.getUtcTime().getValue());
+ Objects.requireNonNull(phoneTimeSuggestion);
- TimestampedValue<Long> utcTime = phoneTimeSuggestion.getUtcTime();
- TelephonyMetrics.getInstance().writeNITZEvent(mPhoneId, utcTime.getValue());
+ if (phoneTimeSuggestion.getUtcTime() != null) {
+ TimestampedValue<Long> utcTime = phoneTimeSuggestion.getUtcTime();
+ TelephonyMetrics.getInstance().writeNITZEvent(mPhoneId, utcTime.getValue());
+ }
mTimeDetector.suggestPhoneTime(phoneTimeSuggestion);
}
@@ -109,14 +111,10 @@
mTimeZoneLog.dump(ipw);
ipw.decreaseIndent();
ipw.decreaseIndent();
-
- // TODO Remove this line when the service moves to the system server.
- mTimeZoneDetector.dumpLogs(ipw);
}
@Override
public void dumpState(PrintWriter pw) {
pw.println(" NewTimeServiceHelperImpl.mLastSuggestedTimeZone=" + mLastSuggestedTimeZone);
- mTimeZoneDetector.dumpState(pw);
}
}
diff --git a/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java b/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java
index c5d9df6..8d8bab9 100644
--- a/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java
+++ b/src/java/com/android/internal/telephony/nitz/TimeZoneSuggesterImpl.java
@@ -16,14 +16,11 @@
package com.android.internal.telephony.nitz;
-import static com.android.internal.telephony.TimeZoneLookupHelper.CountryResult.QUALITY_DEFAULT_BOOSTED;
-import static com.android.internal.telephony.TimeZoneLookupHelper.CountryResult.QUALITY_MULTIPLE_ZONES_DIFFERENT_OFFSETS;
-import static com.android.internal.telephony.TimeZoneLookupHelper.CountryResult.QUALITY_MULTIPLE_ZONES_SAME_OFFSET;
-import static com.android.internal.telephony.TimeZoneLookupHelper.CountryResult.QUALITY_SINGLE_ZONE;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.createEmptySuggestion;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.createEmptySuggestion;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
import android.telephony.Rlog;
import android.text.TextUtils;
import android.util.TimestampedValue;
@@ -34,7 +31,6 @@
import com.android.internal.telephony.TimeZoneLookupHelper;
import com.android.internal.telephony.TimeZoneLookupHelper.CountryResult;
import com.android.internal.telephony.nitz.NewNitzStateMachineImpl.TimeZoneSuggester;
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion;
import java.util.Objects;
@@ -66,11 +62,13 @@
if (nitzSignal != null) {
NitzData nitzData = nitzSignal.getValue();
if (nitzData.getEmulatorHostTimeZone() != null) {
- overridingSuggestion = new PhoneTimeZoneSuggestion(phoneId);
- overridingSuggestion.setZoneId(nitzData.getEmulatorHostTimeZone().getID());
- overridingSuggestion.setMatchType(PhoneTimeZoneSuggestion.EMULATOR_ZONE_ID);
- overridingSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
- overridingSuggestion.addDebugInfo("Emulator time zone override: " + nitzData);
+ PhoneTimeZoneSuggestion.Builder builder =
+ new PhoneTimeZoneSuggestion.Builder(phoneId)
+ .setZoneId(nitzData.getEmulatorHostTimeZone().getID())
+ .setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID)
+ .setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE)
+ .addDebugInfo("Emulator time zone override: " + nitzData);
+ overridingSuggestion = builder.build();
}
}
@@ -125,7 +123,6 @@
+ ", nitzSignal=" + nitzSignal
+ ", e=" + e.getMessage();
PhoneTimeZoneSuggestion errorSuggestion = createEmptySuggestion(phoneId, message);
- errorSuggestion.addDebugInfo(message);
Rlog.w(LOG_TAG, message, e);
return errorSuggestion;
}
@@ -142,21 +139,25 @@
Objects.requireNonNull(nitzSignal);
NitzData nitzData = Objects.requireNonNull(nitzSignal.getValue());
- PhoneTimeZoneSuggestion result = new PhoneTimeZoneSuggestion(phoneId);
- result.addDebugInfo("findTimeZoneForTestNetwork: nitzSignal=" + nitzSignal);
+ PhoneTimeZoneSuggestion.Builder suggestionBuilder =
+ new PhoneTimeZoneSuggestion.Builder(phoneId);
+ suggestionBuilder.addDebugInfo("findTimeZoneForTestNetwork: nitzSignal=" + nitzSignal);
TimeZoneLookupHelper.OffsetResult lookupResult =
mTimeZoneLookupHelper.lookupByNitz(nitzData);
if (lookupResult == null) {
- result.addDebugInfo("findTimeZoneForTestNetwork: No zone found");
+ suggestionBuilder.addDebugInfo("findTimeZoneForTestNetwork: No zone found");
} else {
- result.setZoneId(lookupResult.getTimeZone().getID());
- result.setMatchType(PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY);
- int quality = lookupResult.getIsOnlyMatch() ? PhoneTimeZoneSuggestion.SINGLE_ZONE
- : PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET;
- result.setQuality(quality);
- result.addDebugInfo("findTimeZoneForTestNetwork: lookupResult=" + lookupResult);
+ suggestionBuilder.setZoneId(lookupResult.getTimeZone().getID());
+ suggestionBuilder.setMatchType(
+ PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY);
+ int quality = lookupResult.getIsOnlyMatch()
+ ? PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE
+ : PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+ suggestionBuilder.setQuality(quality);
+ suggestionBuilder.addDebugInfo(
+ "findTimeZoneForTestNetwork: lookupResult=" + lookupResult);
}
- return result;
+ return suggestionBuilder.build();
}
/**
@@ -169,27 +170,32 @@
Objects.requireNonNull(countryIsoCode);
Objects.requireNonNull(nitzSignal);
- PhoneTimeZoneSuggestion suggestion = new PhoneTimeZoneSuggestion(phoneId);
- suggestion.addDebugInfo("findTimeZoneFromCountryAndNitz: countryIsoCode=" + countryIsoCode
+ PhoneTimeZoneSuggestion.Builder suggestionBuilder =
+ new PhoneTimeZoneSuggestion.Builder(phoneId);
+ suggestionBuilder.addDebugInfo("findTimeZoneFromCountryAndNitz:"
+ + " countryIsoCode=" + countryIsoCode
+ ", nitzSignal=" + nitzSignal);
NitzData nitzData = Objects.requireNonNull(nitzSignal.getValue());
if (isNitzSignalOffsetInfoBogus(countryIsoCode, nitzData)) {
- suggestion.addDebugInfo("findTimeZoneFromCountryAndNitz: NITZ signal looks bogus");
- return suggestion;
+ suggestionBuilder.addDebugInfo(
+ "findTimeZoneFromCountryAndNitz: NITZ signal looks bogus");
+ return suggestionBuilder.build();
}
// Try to find a match using both country + NITZ signal.
TimeZoneLookupHelper.OffsetResult lookupResult =
mTimeZoneLookupHelper.lookupByNitzCountry(nitzData, countryIsoCode);
if (lookupResult != null) {
- suggestion.setZoneId(lookupResult.getTimeZone().getID());
- suggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
+ suggestionBuilder.setZoneId(lookupResult.getTimeZone().getID());
+ suggestionBuilder.setMatchType(
+ PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET);
int quality = lookupResult.getIsOnlyMatch()
- ? PhoneTimeZoneSuggestion.SINGLE_ZONE
- : PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET;
- suggestion.setQuality(quality);
- suggestion.addDebugInfo("findTimeZoneFromCountryAndNitz: lookupResult=" + lookupResult);
- return suggestion;
+ ? PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE
+ : PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+ suggestionBuilder.setQuality(quality);
+ suggestionBuilder.addDebugInfo("findTimeZoneFromCountryAndNitz:"
+ + " lookupResult=" + lookupResult);
+ return suggestionBuilder.build();
}
// The country + offset provided no match, so see if the country by itself would be enough.
@@ -197,29 +203,29 @@
countryIsoCode, nitzData.getCurrentTimeInMillis());
if (countryResult == null) {
// Country not recognized.
- suggestion.addDebugInfo(
+ suggestionBuilder.addDebugInfo(
"findTimeZoneFromCountryAndNitz: lookupByCountry() country not recognized");
- return suggestion;
+ return suggestionBuilder.build();
}
// If the country has a single zone, or it has multiple zones but the default zone is
// "boosted" (i.e. the country default is considered a good suggestion in most cases) then
// use it.
- if (countryResult.quality == QUALITY_SINGLE_ZONE
- || countryResult.quality == QUALITY_DEFAULT_BOOSTED) {
- suggestion.setZoneId(countryResult.zoneId);
- suggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- suggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
- suggestion.addDebugInfo(
+ if (countryResult.quality == CountryResult.QUALITY_SINGLE_ZONE
+ || countryResult.quality == CountryResult.QUALITY_DEFAULT_BOOSTED) {
+ suggestionBuilder.setZoneId(countryResult.zoneId);
+ suggestionBuilder.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
+ suggestionBuilder.setQuality(PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE);
+ suggestionBuilder.addDebugInfo(
"findTimeZoneFromCountryAndNitz: high quality country-only suggestion:"
+ " countryResult=" + countryResult);
- return suggestion;
+ return suggestionBuilder.build();
}
// Quality is not high enough to set the zone using country only.
- suggestion.addDebugInfo("findTimeZoneFromCountryAndNitz: country-only suggestion quality"
- + " not high enough. countryResult=" + countryResult);
- return suggestion;
+ suggestionBuilder.addDebugInfo("findTimeZoneFromCountryAndNitz: country-only suggestion"
+ + " quality not high enough. countryResult=" + countryResult);
+ return suggestionBuilder.build();
}
/**
@@ -237,35 +243,39 @@
throw new IllegalArgumentException("countryIsoCode must not be empty");
}
- PhoneTimeZoneSuggestion result = new PhoneTimeZoneSuggestion(phoneId);
- result.addDebugInfo("findTimeZoneFromNetworkCountryCode:"
+ PhoneTimeZoneSuggestion.Builder suggestionBuilder =
+ new PhoneTimeZoneSuggestion.Builder(phoneId);
+ suggestionBuilder.addDebugInfo("findTimeZoneFromNetworkCountryCode:"
+ " whenMillis=" + whenMillis + ", countryIsoCode=" + countryIsoCode);
CountryResult lookupResult = mTimeZoneLookupHelper.lookupByCountry(
countryIsoCode, whenMillis);
if (lookupResult != null) {
- result.setZoneId(lookupResult.zoneId);
- result.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
+ suggestionBuilder.setZoneId(lookupResult.zoneId);
+ suggestionBuilder.setMatchType(PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY);
int quality;
- if (lookupResult.quality == QUALITY_SINGLE_ZONE
- || lookupResult.quality == QUALITY_DEFAULT_BOOSTED) {
- quality = PhoneTimeZoneSuggestion.SINGLE_ZONE;
- } else if (lookupResult.quality == QUALITY_MULTIPLE_ZONES_SAME_OFFSET) {
- quality = PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET;
- } else if (lookupResult.quality == QUALITY_MULTIPLE_ZONES_DIFFERENT_OFFSETS) {
- quality = PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
+ if (lookupResult.quality == CountryResult.QUALITY_SINGLE_ZONE
+ || lookupResult.quality == CountryResult.QUALITY_DEFAULT_BOOSTED) {
+ quality = PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
+ } else if (lookupResult.quality == CountryResult.QUALITY_MULTIPLE_ZONES_SAME_OFFSET) {
+ quality = PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+ } else if (lookupResult.quality
+ == CountryResult.QUALITY_MULTIPLE_ZONES_DIFFERENT_OFFSETS) {
+ quality = PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
} else {
// This should never happen.
throw new IllegalArgumentException(
"lookupResult.quality not recognized: countryIsoCode=" + countryIsoCode
+ ", whenMillis=" + whenMillis + ", lookupResult=" + lookupResult);
}
- result.setQuality(quality);
- result.addDebugInfo("findTimeZoneFromNetworkCountryCode: lookupResult=" + lookupResult);
+ suggestionBuilder.setQuality(quality);
+ suggestionBuilder.addDebugInfo(
+ "findTimeZoneFromNetworkCountryCode: lookupResult=" + lookupResult);
} else {
- result.addDebugInfo("findTimeZoneFromNetworkCountryCode: Country not recognized?");
+ suggestionBuilder.addDebugInfo(
+ "findTimeZoneFromNetworkCountryCode: Country not recognized?");
}
- return result;
+ return suggestionBuilder.build();
}
/**
diff --git a/src/java/com/android/internal/telephony/nitz/service/PhoneTimeZoneSuggestion.java b/src/java/com/android/internal/telephony/nitz/service/PhoneTimeZoneSuggestion.java
deleted file mode 100644
index a5078a7..0000000
--- a/src/java/com/android/internal/telephony/nitz/service/PhoneTimeZoneSuggestion.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright 2019 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.nitz.service;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A suggested time zone from a Phone-based signal, e.g. from MCC and NITZ information.
- */
-public final class PhoneTimeZoneSuggestion implements Parcelable {
-
- public static final Creator<PhoneTimeZoneSuggestion> CREATOR =
- new Creator<PhoneTimeZoneSuggestion>() {
- public PhoneTimeZoneSuggestion createFromParcel(Parcel in) {
- return PhoneTimeZoneSuggestion.createFromParcel(in);
- }
-
- public PhoneTimeZoneSuggestion[] newArray(int size) {
- return new PhoneTimeZoneSuggestion[size];
- }
- };
-
- /**
- * Creates an empty time zone suggestion, i.e. one that will cancel previous suggestions with
- * the same {@code phoneId}.
- */
- @NonNull
- public static PhoneTimeZoneSuggestion createEmptySuggestion(
- int phoneId, @NonNull String debugInfo) {
- PhoneTimeZoneSuggestion timeZoneSuggestion = new PhoneTimeZoneSuggestion(phoneId);
- timeZoneSuggestion.addDebugInfo(debugInfo);
- return timeZoneSuggestion;
- }
-
- @IntDef({ MATCH_TYPE_NA, NETWORK_COUNTRY_ONLY, NETWORK_COUNTRY_AND_OFFSET, EMULATOR_ZONE_ID,
- TEST_NETWORK_OFFSET_ONLY })
- @Retention(RetentionPolicy.SOURCE)
- public @interface MatchType {}
-
- /** Used when match type is not applicable. */
- public static final int MATCH_TYPE_NA = 0;
-
- /**
- * Only the network country is known.
- */
- public static final int NETWORK_COUNTRY_ONLY = 2;
-
- /**
- * Both the network county and offset were known.
- */
- public static final int NETWORK_COUNTRY_AND_OFFSET = 3;
-
- /**
- * The device is running in an emulator and an NITZ signal was simulated containing an
- * Android extension with an explicit Olson ID.
- */
- public static final int EMULATOR_ZONE_ID = 4;
-
- /**
- * The phone is most likely running in a test network not associated with a country (this is
- * distinct from the country just not being known yet).
- * Historically, Android has just picked an arbitrary time zone with the correct offset when
- * on a test network.
- */
- public static final int TEST_NETWORK_OFFSET_ONLY = 5;
-
- @IntDef({ QUALITY_NA, SINGLE_ZONE, MULTIPLE_ZONES_WITH_SAME_OFFSET,
- MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Quality {}
-
- /** Used when quality is not applicable. */
- public static final int QUALITY_NA = 0;
-
- /** There is only one answer */
- public static final int SINGLE_ZONE = 1;
-
- /**
- * There are multiple answers, but they all shared the same offset / DST state at the time
- * the suggestion was created. i.e. it might be the wrong zone but the user won't notice
- * immediately if it is wrong.
- */
- public static final int MULTIPLE_ZONES_WITH_SAME_OFFSET = 2;
-
- /**
- * There are multiple answers with different offsets. The one given is just one possible.
- */
- public static final int MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS = 3;
-
- /**
- * The ID of the phone this suggestion is associated with. For multiple-sim devices this
- * helps to establish origin so filtering / stickiness can be implemented.
- */
- private final int mPhoneId;
-
- /**
- * The suggestion. {@code null} means there is no current suggestion and any previous suggestion
- * should be forgotten.
- */
- private String mZoneId;
-
- /**
- * The type of "match" used to establish the time zone.
- */
- @MatchType
- private int mMatchType;
-
- /**
- * A measure of the quality of the time zone suggestion, i.e. how confident one could be in
- * it.
- */
- @Quality
- private int mQuality;
-
- /**
- * Free-form debug information about how the signal was derived. Used for debug only,
- * intentionally not used in equals(), etc.
- */
- private List<String> mDebugInfo;
-
- public PhoneTimeZoneSuggestion(int phoneId) {
- this.mPhoneId = phoneId;
- }
-
- @SuppressWarnings("unchecked")
- private static PhoneTimeZoneSuggestion createFromParcel(Parcel in) {
- int phoneId = in.readInt();
- PhoneTimeZoneSuggestion phoneTimeZoneSuggestion = new PhoneTimeZoneSuggestion(phoneId);
- phoneTimeZoneSuggestion.mZoneId = in.readString();
- phoneTimeZoneSuggestion.mMatchType = in.readInt();
- phoneTimeZoneSuggestion.mQuality = in.readInt();
- phoneTimeZoneSuggestion.mDebugInfo =
- (List<String>) in.readArrayList(PhoneTimeZoneSuggestion.class.getClassLoader());
- return phoneTimeZoneSuggestion;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mPhoneId);
- dest.writeString(mZoneId);
- dest.writeInt(mMatchType);
- dest.writeInt(mQuality);
- dest.writeList(mDebugInfo);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public int getPhoneId() {
- return mPhoneId;
- }
-
- @Nullable
- public String getZoneId() {
- return mZoneId;
- }
-
- public void setZoneId(@Nullable String zoneId) {
- this.mZoneId = zoneId;
- }
-
-
- @MatchType
- public int getMatchType() {
- return mMatchType;
- }
-
- public void setMatchType(@MatchType int matchType) {
- this.mMatchType = matchType;
- }
- @Quality
- public int getQuality() {
- return mQuality;
- }
-
- public void setQuality(@Quality int quality) {
- this.mQuality = quality;
- }
-
- public List<String> getDebugInfo() {
- return Collections.unmodifiableList(mDebugInfo);
- }
-
- /**
- * Associates information with the instance that can be useful for debugging / logging. The
- * information is present in {@link #toString()} but is not considered for
- * {@link #equals(Object)} and {@link #hashCode()}.
- */
- public void addDebugInfo(String... debugInfos) {
- if (mDebugInfo == null) {
- mDebugInfo = new ArrayList<>();
- }
- mDebugInfo.addAll(Arrays.asList(debugInfos));
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- PhoneTimeZoneSuggestion that = (PhoneTimeZoneSuggestion) o;
- return mPhoneId == that.mPhoneId
- && mMatchType == that.mMatchType
- && mQuality == that.mQuality
- && Objects.equals(mZoneId, that.mZoneId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mPhoneId, mZoneId, mMatchType, mQuality);
- }
-
- @Override
- public String toString() {
- return "PhoneTimeZoneSuggestion{"
- + "mPhoneId=" + mPhoneId
- + ", mZoneId='" + mZoneId + '\''
- + ", mMatchType=" + mMatchType
- + ", mQuality=" + mQuality
- + ", mDebugInfo=" + mDebugInfo
- + '}';
- }
-}
diff --git a/src/java/com/android/internal/telephony/nitz/service/TimeZoneDetectionService.java b/src/java/com/android/internal/telephony/nitz/service/TimeZoneDetectionService.java
deleted file mode 100644
index a766d9a..0000000
--- a/src/java/com/android/internal/telephony/nitz/service/TimeZoneDetectionService.java
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright 2019 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.nitz.service;
-
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.EMULATOR_ZONE_ID;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.MATCH_TYPE_NA;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.QUALITY_NA;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.SINGLE_ZONE;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.io.PrintWriter;
-import java.util.LinkedList;
-import java.util.Objects;
-
-/**
- * A singleton, stateful time zone detection service that is aware of multiple phone devices. It
- * keeps track of the most recent suggestion from each phone and it uses the best based on a scoring
- * algorithm. If both phones provide the same score then the phone with the lowest numeric ID
- * "wins". If the situation changes and it is no longer possible to be confident about the time
- * zone, phones must submit an empty suggestion in order to "withdraw" their previous suggestion.
- *
- * <p>Ultimately, this responsibility will be moved to system server and then it will be extended /
- * rewritten to handle non-telephony time zone signals.
- */
-public class TimeZoneDetectionService {
-
- /**
- * Used by {@link TimeZoneDetectionService} to interact with device settings. It can be faked
- * for tests.
- */
- @VisibleForTesting
- public interface Helper {
-
- /**
- * Callback interface for automatic detection enable/disable changes.
- */
- interface Listener {
- /**
- * Automatic time zone detection has been enabled or disabled.
- */
- void onTimeZoneDetectionChange(boolean enabled);
- }
-
- /**
- * Sets a listener that will be called when the automatic time / time zone detection setting
- * changes.
- */
- void setListener(Listener listener);
-
- /**
- * Returns true if automatic time zone detection is enabled in settings.
- */
- boolean isTimeZoneDetectionEnabled();
-
- /**
- * Returns true if the device has had an explicit time zone set.
- */
- boolean isTimeZoneSettingInitialized();
-
- /**
- * Set the device time zone from the suggestion as needed.
- */
- void setDeviceTimeZoneFromSuggestion(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion);
-
- /**
- * Dumps any logs held to the supplied writer.
- */
- void dumpLogs(IndentingPrintWriter ipw);
-
- /**
- * Dumps internal state such as field values.
- */
- void dumpState(PrintWriter pw);
- }
-
- static final String LOG_TAG = "TimeZoneDetectionService";
- static final boolean DBG = true;
-
- /**
- * The abstract score for an empty or invalid suggestion.
- *
- * Used to score suggestions where there is no zone.
- */
- @VisibleForTesting
- public static final int SCORE_NONE = 0;
-
- /**
- * The abstract score for a low quality suggestion.
- *
- * Used to score suggestions where:
- * The suggested zone ID is one of several possibilities, and the possibilities have different
- * offsets.
- *
- * You would have to be quite desperate to want to use this choice.
- */
- @VisibleForTesting
- public static final int SCORE_LOW = 1;
-
- /**
- * The abstract score for a medium quality suggestion.
- *
- * Used for:
- * The suggested zone ID is one of several possibilities but at least the possibilities have the
- * same offset. Users would get the correct time but for the wrong reason. i.e. their device may
- * switch to DST at the wrong time and (for example) their calendar events.
- */
- @VisibleForTesting
- public static final int SCORE_MEDIUM = 2;
-
- /**
- * The abstract score for a high quality suggestion.
- *
- * Used for:
- * The suggestion was for one zone ID and the answer was unambiguous and likely correct given
- * the info available.
- */
- @VisibleForTesting
- public static final int SCORE_HIGH = 3;
-
- /**
- * The abstract score for a highest quality suggestion.
- *
- * Used for:
- * Suggestions that must "win" because they constitute test or emulator zone ID.
- */
- @VisibleForTesting
- public static final int SCORE_HIGHEST = 4;
-
- /** The threshold at which suggestions are good enough to use to set the device's time zone. */
- @VisibleForTesting
- public static final int SCORE_USAGE_THRESHOLD = SCORE_MEDIUM;
-
- /** The singleton instance. */
- private static TimeZoneDetectionService sInstance;
-
- /**
- * Returns the singleton instance, constructing as needed with the supplied context.
- */
- public static synchronized TimeZoneDetectionService getInstance(Context context) {
- if (sInstance == null) {
- Helper timeZoneDetectionServiceHelper = new TimeZoneDetectionServiceHelperImpl(context);
- sInstance = new TimeZoneDetectionService(timeZoneDetectionServiceHelper);
- }
- return sInstance;
- }
-
- private static final int KEEP_SUGGESTION_HISTORY_SIZE = 30;
-
- /**
- * A mapping from phoneId to a linked list of time zone suggestions (the head being the latest).
- * We typically expect one or two entries in this Map: devices will have a small number
- * of telephony devices and phoneIds are assumed to be stable. The LinkedList associated with
- * the ID will not exceed {@link #KEEP_SUGGESTION_HISTORY_SIZE} in size.
- */
- @GuardedBy("this")
- private ArrayMap<Integer, LinkedList<QualifiedPhoneTimeZoneSuggestion>> mSuggestionByPhoneId =
- new ArrayMap<>();
-
- /**
- * The most recent best guess of time zone from all phones. Can be {@code null} to indicate
- * there would be no current suggestion.
- */
- @GuardedBy("this")
- @Nullable
- private QualifiedPhoneTimeZoneSuggestion mCurrentSuggestion;
-
- // Dependencies and log state.
- private final Helper mTimeZoneDetectionServiceHelper;
-
- @VisibleForTesting
- public TimeZoneDetectionService(Helper timeZoneDetectionServiceHelper) {
- mTimeZoneDetectionServiceHelper = timeZoneDetectionServiceHelper;
- mTimeZoneDetectionServiceHelper.setListener(enabled -> {
- if (enabled) {
- handleAutoTimeZoneEnabled();
- }
- });
- }
-
- /**
- * Suggests a time zone for the device, or withdraws a previous suggestion if
- * {@link PhoneTimeZoneSuggestion#getZoneId()} is {@code null}. The suggestion is scoped to a
- * specific {@link PhoneTimeZoneSuggestion#getPhoneId() phone}.
- * See {@link PhoneTimeZoneSuggestion} for an explanation of the metadata associated with a
- * suggestion. The service uses suggestions to decide whether to modify the device's time zone
- * setting and what to set it to.
- */
- public synchronized void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion newSuggestion) {
- if (DBG) {
- Log.d(LOG_TAG, "suggestPhoneTimeZone: newSuggestion=" + newSuggestion);
- }
- Objects.requireNonNull(newSuggestion);
-
- int score = scoreSuggestion(newSuggestion);
- QualifiedPhoneTimeZoneSuggestion scoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(newSuggestion, score);
-
- // Record the suggestion against the correct phoneId.
- LinkedList<QualifiedPhoneTimeZoneSuggestion> suggestions =
- mSuggestionByPhoneId.get(newSuggestion.getPhoneId());
- if (suggestions == null) {
- suggestions = new LinkedList<>();
- mSuggestionByPhoneId.put(newSuggestion.getPhoneId(), suggestions);
- }
- suggestions.addFirst(scoredSuggestion);
- if (suggestions.size() > KEEP_SUGGESTION_HISTORY_SIZE) {
- suggestions.removeLast();
- }
-
- // Now run the competition between the phones' suggestions.
- doTimeZoneDetection();
- }
-
- private static int scoreSuggestion(@NonNull PhoneTimeZoneSuggestion suggestion) {
- int score;
- if (suggestion.getZoneId() == null || !isValid(suggestion)) {
- score = SCORE_NONE;
- } else if (suggestion.getMatchType() == TEST_NETWORK_OFFSET_ONLY
- || suggestion.getMatchType() == EMULATOR_ZONE_ID) {
- // Handle emulator / test cases : These suggestions should always just be used.
- score = SCORE_HIGHEST;
- } else if (suggestion.getQuality() == SINGLE_ZONE) {
- score = SCORE_HIGH;
- } else if (suggestion.getQuality() == MULTIPLE_ZONES_WITH_SAME_OFFSET) {
- // The suggestion may be wrong, but at least the offset should be correct.
- score = SCORE_MEDIUM;
- } else if (suggestion.getQuality() == MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS) {
- // The suggestion has a good chance of being wrong.
- score = SCORE_LOW;
- } else {
- throw new AssertionError();
- }
- return score;
- }
-
- private static boolean isValid(@NonNull PhoneTimeZoneSuggestion suggestion) {
- int quality = suggestion.getQuality();
- int matchType = suggestion.getMatchType();
- if (suggestion.getZoneId() == null) {
- return quality == QUALITY_NA && matchType == MATCH_TYPE_NA;
- } else {
- boolean qualityValid = quality == SINGLE_ZONE
- || quality == MULTIPLE_ZONES_WITH_SAME_OFFSET
- || quality == MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
- boolean matchTypeValid = matchType == NETWORK_COUNTRY_ONLY
- || matchType == NETWORK_COUNTRY_AND_OFFSET
- || matchType == EMULATOR_ZONE_ID
- || matchType == TEST_NETWORK_OFFSET_ONLY;
- return qualityValid && matchTypeValid;
- }
- }
-
- /**
- * Finds the best available time zone suggestion from all phones. If it is high-enough quality
- * and automatic time zone detection is enabled then it will be set on the device. The outcome
- * can be that this service becomes / remains un-opinionated and nothing is set.
- */
- @GuardedBy("this")
- private void doTimeZoneDetection() {
- QualifiedPhoneTimeZoneSuggestion bestSuggestion = findBestSuggestion();
- boolean timeZoneDetectionEnabled =
- mTimeZoneDetectionServiceHelper.isTimeZoneDetectionEnabled();
-
- // Work out what to do with the best suggestion.
- if (bestSuggestion == null) {
- // There is no suggestion. Become un-opinionated.
- if (DBG) {
- Log.d(LOG_TAG, "doTimeZoneDetection: No good suggestion."
- + " bestSuggestion=null"
- + ", timeZoneDetectionEnabled=" + timeZoneDetectionEnabled);
- }
- mCurrentSuggestion = null;
- return;
- }
-
- // Special case handling for uninitialized devices. This should only happen once.
- String newZoneId = bestSuggestion.suggestion.getZoneId();
- if (newZoneId != null && !mTimeZoneDetectionServiceHelper.isTimeZoneSettingInitialized()) {
- Log.i(LOG_TAG, "doTimeZoneDetection: Device has no time zone set so might set the"
- + " device to the best available suggestion."
- + " bestSuggestion=" + bestSuggestion
- + ", timeZoneDetectionEnabled=" + timeZoneDetectionEnabled);
-
- mCurrentSuggestion = bestSuggestion;
- if (timeZoneDetectionEnabled) {
- mTimeZoneDetectionServiceHelper.setDeviceTimeZoneFromSuggestion(
- bestSuggestion.suggestion);
- }
- return;
- }
-
- boolean suggestionGoodEnough = bestSuggestion.score >= SCORE_USAGE_THRESHOLD;
- if (!suggestionGoodEnough) {
- if (DBG) {
- Log.d(LOG_TAG, "doTimeZoneDetection: Suggestion not good enough."
- + " bestSuggestion=" + bestSuggestion);
- }
- mCurrentSuggestion = null;
- return;
- }
-
- // Paranoia: Every suggestion above the SCORE_USAGE_THRESHOLD should have a non-null time
- // zone ID.
- if (newZoneId == null) {
- Log.w(LOG_TAG, "Empty zone suggestion scored higher than expected. This is an error:"
- + " bestSuggestion=" + bestSuggestion);
- mCurrentSuggestion = null;
- return;
- }
-
- // There is a good suggestion. Store the suggestion and set the device time zone if
- // settings allow.
- mCurrentSuggestion = bestSuggestion;
-
- // Only set the device time zone if time zone detection is enabled.
- if (!timeZoneDetectionEnabled) {
- if (DBG) {
- Log.d(LOG_TAG, "doTimeZoneDetection: Not setting the time zone because time zone"
- + " detection is disabled."
- + " bestSuggestion=" + bestSuggestion);
- }
- return;
- }
- mTimeZoneDetectionServiceHelper.setDeviceTimeZoneFromSuggestion(bestSuggestion.suggestion);
- }
-
- @GuardedBy("this")
- @Nullable
- private QualifiedPhoneTimeZoneSuggestion findBestSuggestion() {
- QualifiedPhoneTimeZoneSuggestion bestSuggestion = null;
-
- // Iterate over the latest QualifiedPhoneTimeZoneSuggestion objects received for each phone
- // and find the best. Note that we deliberately do not look at age: the caller can
- // rate-limit so age is not a strong indicator of confidence. Instead, the callers are
- // expected to withdraw suggestions they no longer have confidence in.
- for (int i = 0; i < mSuggestionByPhoneId.size(); i++) {
- LinkedList<QualifiedPhoneTimeZoneSuggestion> phoneSuggestions =
- mSuggestionByPhoneId.valueAt(i);
- if (phoneSuggestions == null) {
- // Unexpected
- continue;
- }
- QualifiedPhoneTimeZoneSuggestion candidateSuggestion = phoneSuggestions.getFirst();
- if (candidateSuggestion == null) {
- // Unexpected
- continue;
- }
-
- if (bestSuggestion == null) {
- bestSuggestion = candidateSuggestion;
- } else if (candidateSuggestion.score > bestSuggestion.score) {
- bestSuggestion = candidateSuggestion;
- } else if (candidateSuggestion.score == bestSuggestion.score) {
- // Tie! Use the suggestion with the lowest phoneId.
- int candidatePhoneId = candidateSuggestion.suggestion.getPhoneId();
- int bestPhoneId = bestSuggestion.suggestion.getPhoneId();
- if (candidatePhoneId < bestPhoneId) {
- bestSuggestion = candidateSuggestion;
- }
- }
- }
- return bestSuggestion;
- }
-
- /**
- * Returns the current best suggestion. Not intended for general use: it is used during tests
- * to check service behavior.
- */
- @VisibleForTesting
- @Nullable
- public synchronized QualifiedPhoneTimeZoneSuggestion findBestSuggestionForTests() {
- return findBestSuggestion();
- }
-
- private synchronized void handleAutoTimeZoneEnabled() {
- if (DBG) {
- Log.d(LOG_TAG, "handleAutoTimeEnabled() called");
- }
- // When the user enabled time zone detection, run the time zone detection and change the
- // device time zone if possible.
- doTimeZoneDetection();
- }
-
- /**
- * Dumps any logs held to the supplied writer.
- */
- public void dumpLogs(IndentingPrintWriter ipw) {
- mTimeZoneDetectionServiceHelper.dumpLogs(ipw);
- }
-
- /**
- * Dumps internal state such as field values.
- */
- public void dumpState(PrintWriter pw) {
- pw.println(" TimeZoneDetectionService.mCurrentSuggestion=" + mCurrentSuggestion);
- pw.println(" TimeZoneDetectionService.mSuggestionsByPhoneId=" + mSuggestionByPhoneId);
- mTimeZoneDetectionServiceHelper.dumpState(pw);
- pw.flush();
- }
-
- /**
- * A method used to inspect service state during tests. Not intended for general use.
- */
- @VisibleForTesting
- public synchronized QualifiedPhoneTimeZoneSuggestion getLatestPhoneSuggestion(int phoneId) {
- LinkedList<QualifiedPhoneTimeZoneSuggestion> suggestions =
- mSuggestionByPhoneId.get(phoneId);
- if (suggestions == null) {
- return null;
- }
- return suggestions.getFirst();
- }
-
- /**
- * A {@link PhoneTimeZoneSuggestion} with additional qualifying metadata.
- */
- @VisibleForTesting
- public static class QualifiedPhoneTimeZoneSuggestion {
-
- @VisibleForTesting
- public final PhoneTimeZoneSuggestion suggestion;
-
- /**
- * The score the suggestion has been given. This can be used to rank against other
- * suggestions of the same type.
- */
- @VisibleForTesting
- public final int score;
-
- @VisibleForTesting
- public QualifiedPhoneTimeZoneSuggestion(PhoneTimeZoneSuggestion suggestion, int score) {
- this.suggestion = suggestion;
- this.score = score;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- QualifiedPhoneTimeZoneSuggestion that = (QualifiedPhoneTimeZoneSuggestion) o;
- return score == that.score
- && suggestion.equals(that.suggestion);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(score, suggestion);
- }
-
- @Override
- public String toString() {
- return "QualifiedPhoneTimeZoneSuggestion{"
- + "suggestion=" + suggestion
- + ", score=" + score
- + '}';
- }
- }
-}
diff --git a/src/java/com/android/internal/telephony/nitz/service/TimeZoneDetectionServiceHelperImpl.java b/src/java/com/android/internal/telephony/nitz/service/TimeZoneDetectionServiceHelperImpl.java
deleted file mode 100644
index fc857a7..0000000
--- a/src/java/com/android/internal/telephony/nitz/service/TimeZoneDetectionServiceHelperImpl.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright 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.nitz.service;
-
-import android.annotation.Nullable;
-import android.app.AlarmManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.LocalLog;
-import android.util.Log;
-
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.util.IndentingPrintWriter;
-
-import java.io.PrintWriter;
-
-/**
- * The real implementation of {@link TimeZoneDetectionService.Helper}.
- */
-public final class TimeZoneDetectionServiceHelperImpl implements TimeZoneDetectionService.Helper {
-
- private static final String LOG_TAG = TimeZoneDetectionService.LOG_TAG;
- private static final boolean DBG = TimeZoneDetectionService.DBG;
- private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
-
- private final Context mContext;
- private final ContentResolver mCr;
- private final LocalLog mTimeZoneLog = new LocalLog(30);
-
- private Listener mListener;
-
- /** Creates a TimeServiceHelper */
- public TimeZoneDetectionServiceHelperImpl(Context context) {
- mContext = context;
- mCr = context.getContentResolver();
- }
-
- @Override
- public void setListener(Listener listener) {
- if (listener == null) {
- throw new NullPointerException("listener==null");
- }
- if (mListener != null) {
- throw new IllegalStateException("listener already set");
- }
- this.mListener = listener;
- mCr.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true,
- new ContentObserver(new Handler()) {
- public void onChange(boolean selfChange) {
- listener.onTimeZoneDetectionChange(isTimeZoneDetectionEnabled());
- }
- });
- }
-
- @Override
- public boolean isTimeZoneDetectionEnabled() {
- try {
- return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0;
- } catch (Settings.SettingNotFoundException snfe) {
- return true;
- }
- }
-
- @Override
- public boolean isTimeZoneSettingInitialized() {
- // timezone.equals("GMT") will be true and only true if the time zone was
- // set to a default value by the system server (when starting, system server
- // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by
- // any code that sets it explicitly (in case where something sets GMT explicitly,
- // "Etc/GMT" Olson ID would be used).
-
- String timeZoneId = getTimeZoneSetting();
- return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT");
- }
-
- @Override
- public void setDeviceTimeZoneFromSuggestion(PhoneTimeZoneSuggestion timeZoneSuggestion) {
- String currentZoneId = getTimeZoneSetting();
- String newZoneId = timeZoneSuggestion.getZoneId();
- if (newZoneId.equals(currentZoneId)) {
- // No need to set the device time zone - the setting is already what we would be
- // suggesting.
- if (DBG) {
- Log.d(LOG_TAG, "setDeviceTimeZoneAsNeeded: No need to change the time zone;"
- + " device is already set to the suggested zone."
- + " timeZoneSuggestion=" + timeZoneSuggestion);
- }
- return;
- }
-
- String msg = "Changing device time zone. currentZoneId=" + currentZoneId
- + ", timeZoneSuggestion=" + timeZoneSuggestion;
- if (DBG) {
- Log.d(LOG_TAG, msg);
- }
- mTimeZoneLog.log(msg);
-
- AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- alarmManager.setTimeZone(newZoneId);
- Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra("time-zone", newZoneId);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- @Nullable
- private String getTimeZoneSetting() {
- return SystemProperties.get(TIMEZONE_PROPERTY);
- }
-
- @Override
- public void dumpState(PrintWriter pw) {
- pw.println(" TimeZoneDetectionServiceHelperImpl.getTimeZoneSetting()="
- + getTimeZoneSetting());
- }
-
- @Override
- public void dumpLogs(IndentingPrintWriter ipw) {
- ipw.println("TimeZoneDetectionServiceHelperImpl:");
-
- ipw.increaseIndent();
- ipw.println("Time zone logs:");
- ipw.increaseIndent();
- mTimeZoneLog.dump(ipw);
- ipw.decreaseIndent();
-
- ipw.decreaseIndent();
- }
-}
diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index f3c8afe..0307363 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.uicc;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.AsyncResult;
@@ -742,6 +743,23 @@
return mSpn;
}
+ /**
+ * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41) or
+ * the brand override. The brand override has higher priority than the SPN from SIM.
+ *
+ * @return service provider name.
+ */
+ @Nullable
+ public String getServiceProviderNameWithBrandOverride() {
+ if (mParentApp != null && mParentApp.getUiccProfile() != null) {
+ String brandOverride = mParentApp.getUiccProfile().getOperatorBrandOverride();
+ if (!TextUtils.isEmpty(brandOverride)) {
+ return brandOverride;
+ }
+ }
+ return mSpn;
+ }
+
protected void setServiceProviderName(String spn) {
if (!TextUtils.equals(mSpn, spn)) {
mSpn = spn != null ? spn.trim() : null;
diff --git a/src/java/com/android/internal/telephony/uicc/RuimRecords.java b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
index ca673f0..5a1a8ac 100644
--- a/src/java/com/android/internal/telephony/uicc/RuimRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
@@ -326,7 +326,7 @@
// SPN is checked to have characters in printable ASCII
// range. If not, they are decoded with
// ENCODING_GSM_7BIT_ALPHABET scheme.
- if (TextUtils.isPrintableAsciiOnly(spn)) {
+ if (isPrintableAsciiOnly(spn)) {
setServiceProviderName(spn);
} else {
if (DBG) log("Some corruption in SPN decoding = " + spn);
@@ -351,6 +351,22 @@
}
}
+ private static boolean isPrintableAsciiOnly(final CharSequence str) {
+ final int len = str.length();
+ for (int i = 0; i < len; i++) {
+ if (!isPrintableAscii(str.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isPrintableAscii(final char c) {
+ final int asciiFirst = 0x20;
+ final int asciiLast = 0x7E; // included
+ return (asciiFirst <= c && c <= asciiLast) || c == '\r' || c == '\n';
+ }
+
private class EfCsimMdnLoaded implements IccRecordLoaded {
@Override
public String getEfName() {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
index 0c4629b..2585e26 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRules.java
@@ -316,7 +316,7 @@
// is disabled by default, and some other component wants to enable it when it has
// gained carrier privileges (as an indication that a matching SIM has been inserted).
PackageInfo pInfo = packageManager.getPackageInfo(packageName,
- PackageManager.GET_SIGNATURES
+ PackageManager.GET_SIGNING_CERTIFICATES
| PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS);
return getCarrierPrivilegeStatus(pInfo);
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 6112dda..720ad75 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -19,6 +19,8 @@
import static android.telephony.TelephonyManager.UNINITIALIZED_CARD_ID;
import static android.telephony.TelephonyManager.UNSUPPORTED_CARD_ID;
+import static java.util.Arrays.copyOf;
+
import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.content.Context;
@@ -43,6 +45,7 @@
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneConfigurationManager;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.RadioConfig;
@@ -121,6 +124,7 @@
private static final int EVENT_RADIO_UNAVAILABLE = 7;
private static final int EVENT_SIM_REFRESH = 8;
private static final int EVENT_EID_READY = 9;
+ private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 10;
// this needs to be here, because on bootup we dont know which index maps to which UiccSlot
@UnsupportedAppUsage
@@ -187,20 +191,23 @@
// LocalLog buffer to hold important SIM related events for debugging
static LocalLog sLocalLog = new LocalLog(100);
- public static UiccController make(Context c, CommandsInterface[] ci) {
+ /**
+ * API to make UiccController singleton if not already created.
+ */
+ public static UiccController make(Context c) {
synchronized (mLock) {
if (mInstance != null) {
throw new RuntimeException("UiccController.make() should only be called once");
}
- mInstance = new UiccController(c, ci);
+ mInstance = new UiccController(c);
return mInstance;
}
}
- private UiccController(Context c, CommandsInterface []ci) {
+ private UiccController(Context c) {
if (DBG) log("Creating UiccController");
mContext = c;
- mCis = ci;
+ mCis = PhoneFactory.getCommandsInterfaces();
if (DBG) {
String logStr = "config_num_physical_slots = " + c.getResources().getInteger(
com.android.internal.R.integer.config_num_physical_slots);
@@ -216,7 +223,7 @@
}
mUiccSlots = new UiccSlot[numPhysicalSlots];
- mPhoneIdToSlotId = new int[ci.length];
+ mPhoneIdToSlotId = new int[mCis.length];
Arrays.fill(mPhoneIdToSlotId, INVALID_SLOT_ID);
if (VDBG) logPhoneIdToSlotIdMapping();
mRadioConfig = RadioConfig.getInstance(mContext);
@@ -245,6 +252,9 @@
mEuiccSlots = mContext.getResources()
.getIntArray(com.android.internal.R.array.non_removable_euicc_slots);
mHasBuiltInEuicc = hasBuiltInEuicc();
+
+ PhoneConfigurationManager.registerForMultiSimConfigChange(
+ this, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
}
/**
@@ -519,6 +529,9 @@
if (DBG) log("Received EVENT_EID_READY");
onEidReady(ar, phoneId);
break;
+ case EVENT_MULTI_SIM_CONFIG_CHANGED:
+ if (DBG) log("Received EVENT_MULTI_SIM_CONFIG_CHANGED");
+ onMultiSimConfigChanged();
default:
Rlog.e(LOG_TAG, " Unknown Event " + msg.what);
break;
@@ -526,6 +539,36 @@
}
}
+ private void onMultiSimConfigChanged() {
+ int prevActiveModemCount = mCis.length;
+ mCis = PhoneFactory.getCommandsInterfaces();
+
+ // Resize array.
+ mPhoneIdToSlotId = copyOf(mPhoneIdToSlotId, mCis.length);
+
+ // Register for new active modem for ss -> ds switch.
+ // For ds -> ss switch, there's no need to unregister as the mCis should unregister
+ // everything itself.
+ for (int i = prevActiveModemCount; i < mCis.length; i++) {
+ mPhoneIdToSlotId[i] = INVALID_SLOT_ID;
+ mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i);
+
+ /*
+ * To support FDE (deprecated), additional check is needed:
+ *
+ * if (!StorageManager.inCryptKeeperBounce()) {
+ * mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i);
+ * } else {
+ * mCis[i].registerForOn(this, EVENT_RADIO_ON, i);
+ * }
+ */
+ mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i);
+
+ mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, i);
+ mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i);
+ }
+ }
+
private Integer getCiIndex(Message msg) {
AsyncResult ar;
Integer index = new Integer(PhoneConstants.DEFAULT_SLOT_INDEX);
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index 11478e6..0c2c60b 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -26,6 +26,7 @@
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
+import android.os.UserHandle;
import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -105,9 +106,9 @@
// 2. The latest mCardState is not ABSENT, but there is no UiccCard instance.
} else if ((oldState == null || oldState == CardState.CARDSTATE_ABSENT
|| mUiccCard == null) && mCardState != CardState.CARDSTATE_ABSENT) {
- // No notifications while radio is off or we just powering up
- if (radioState == TelephonyManager.RADIO_POWER_ON
- && mLastRadioState == TelephonyManager.RADIO_POWER_ON) {
+ // No notification while we are just powering up
+ if (radioState != TelephonyManager.RADIO_POWER_UNAVAILABLE
+ && mLastRadioState != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
if (DBG) log("update: notify card added");
sendMessage(obtainMessage(EVENT_CARD_ADDED, null));
}
@@ -183,9 +184,9 @@
private void updateCardStateAbsent() {
int radioState =
(mCi == null) ? TelephonyManager.RADIO_POWER_UNAVAILABLE : mCi.getRadioState();
- // No notifications while radio is off or we just powering up
- if (radioState == TelephonyManager.RADIO_POWER_ON
- && mLastRadioState == TelephonyManager.RADIO_POWER_ON) {
+ // No notification while we are just powering up
+ if (radioState != TelephonyManager.RADIO_POWER_UNAVAILABLE
+ && mLastRadioState != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
if (DBG) log("update: notify card removed");
sendMessage(obtainMessage(EVENT_CARD_REMOVED, null));
}
@@ -319,7 +320,7 @@
dialogComponent)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_ICC_CARD_ADDED, isAdded);
try {
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT);
return;
} catch (ActivityNotFoundException e) {
loge("Unable to find ICC hotswap prompt for restart activity: " + e);
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
index 1f72ae8..00b4945 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.os.Handler;
+import android.os.Looper;
import android.telephony.IccOpenLogicalChannelResponse;
import android.telephony.Rlog;
@@ -50,10 +51,16 @@
private static final int STATUS_NO_ERROR = 0x9000;
private static final int SW1_NO_ERROR = 0x91;
+ private static final int WAIT_TIME_MS = 2000;
+
private static void logv(String msg) {
Rlog.v(LOG_TAG, msg);
}
+ private static void logd(String msg) {
+ Rlog.d(LOG_TAG, msg);
+ }
+
private final String mAid;
private final boolean mSupportExtendedApdu;
private final OpenLogicalChannelInvocation mOpenChannel;
@@ -94,10 +101,25 @@
Handler handler) {
synchronized (mChannelLock) {
if (mChannelOpened) {
- AsyncResultHelper.throwException(
- new ApduException("Logical channel has already been opened."),
- resultCallback, handler);
- return;
+ if (!Looper.getMainLooper().equals(Looper.myLooper())) {
+ logd("Logical channel has already been opened. Wait.");
+ try {
+ mChannelLock.wait(WAIT_TIME_MS);
+ } catch (InterruptedException e) {
+ // nothing to do
+ }
+ if (mChannelOpened) {
+ AsyncResultHelper.throwException(
+ new ApduException("The logical channel is still in use."),
+ resultCallback, handler);
+ return;
+ }
+ } else {
+ AsyncResultHelper.throwException(
+ new ApduException("The logical channel is in use."),
+ resultCallback, handler);
+ return;
+ }
}
mChannelOpened = true;
}
@@ -111,6 +133,7 @@
|| status != IccOpenLogicalChannelResponse.STATUS_NO_ERROR) {
synchronized (mChannelLock) {
mChannelOpened = false;
+ mChannelLock.notify();
}
resultCallback.onException(
new ApduException("Failed to open logical channel opened for AID: "
@@ -245,6 +268,7 @@
public void onResult(Boolean aBoolean) {
synchronized (mChannelLock) {
mChannelOpened = false;
+ mChannelLock.notify();
}
if (exception == null) {
diff --git a/src/java/com/android/internal/telephony/util/TelephonyUtils.java b/src/java/com/android/internal/telephony/util/TelephonyUtils.java
index 1048e5c..ea44d98 100644
--- a/src/java/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/src/java/com/android/internal/telephony/util/TelephonyUtils.java
@@ -25,6 +25,8 @@
* This class provides various util functions
*/
public final class TelephonyUtils {
+ public static boolean IS_USER = "user".equals(android.os.Build.TYPE);
+
/** {@hide} */
public static String emptyIfNull(@Nullable String str) {
return str == null ? "" : str;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CbGeoUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/CbGeoUtilsTest.java
index 787cb43..f9b3599 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CbGeoUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CbGeoUtilsTest.java
@@ -18,10 +18,11 @@
import static com.google.common.truth.Truth.assertThat;
-import com.android.internal.telephony.CbGeoUtils.Circle;
-import com.android.internal.telephony.CbGeoUtils.Geometry;
-import com.android.internal.telephony.CbGeoUtils.LatLng;
-import com.android.internal.telephony.CbGeoUtils.Polygon;
+import android.telephony.CbGeoUtils;
+import android.telephony.CbGeoUtils.Circle;
+import android.telephony.CbGeoUtils.Geometry;
+import android.telephony.CbGeoUtils.LatLng;
+import android.telephony.CbGeoUtils.Polygon;
import org.junit.Test;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index fc4dcc6..40cec03 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -61,7 +61,6 @@
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.telephony.TelephonyRegistryManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Telephony.ServiceStateTable;
@@ -69,6 +68,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.telephony.euicc.EuiccManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
@@ -451,6 +451,20 @@
}
@Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission,
+ String receiverAppOp, Bundle options, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
+ logd("sendOrderedBroadcast called for " + intent.getAction());
+ mLastBroadcastOptions = options;
+ sendBroadcast(intent);
+ if (resultReceiver != null) {
+ synchronized (mOrderedBroadcastReceivers) {
+ mOrderedBroadcastReceivers.put(intent, resultReceiver);
+ }
+ }
+ }
+
+ @Override
public void sendStickyBroadcast(Intent intent) {
logd("sendStickyBroadcast called for " + intent.getAction());
synchronized (mBroadcastReceiversByAction) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 5c09525..ae8dd62 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -158,14 +158,6 @@
public void testGetMergedServiceState() throws Exception {
ServiceState imsServiceState = new ServiceState();
- NetworkRegistrationInfo imsCsWwanRegInfo = new NetworkRegistrationInfo.Builder()
- .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
- .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
- .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
- .setRegistrationState(
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
- .build();
-
NetworkRegistrationInfo imsPsWwanRegInfo = new NetworkRegistrationInfo.Builder()
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
@@ -182,10 +174,11 @@
NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.build();
- imsServiceState.addNetworkRegistrationInfo(imsCsWwanRegInfo);
+ // Only PS states are tracked for IMS.
imsServiceState.addNetworkRegistrationInfo(imsPsWwanRegInfo);
imsServiceState.addNetworkRegistrationInfo(imsPsWlanRegInfo);
+ // Voice reg state in this case is whether or not IMS is registered.
imsServiceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
imsServiceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
imsServiceState.setIwlanPreferred(true);
@@ -236,6 +229,88 @@
assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, mergedServiceState.getDataNetworkType());
}
+ /**
+ * Some vendors do not provide a voice registration for LTE when attached to LTE only (no CSFB
+ * available). In this case, we should still get IN_SERVICE for voice service state, since
+ * IMS is registered.
+ */
+ @Test
+ @SmallTest
+ public void testGetMergedServiceStateNoCsfb() throws Exception {
+ ServiceState imsServiceState = new ServiceState();
+
+ NetworkRegistrationInfo imsPsWwanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .build();
+
+ NetworkRegistrationInfo imsPsWlanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .build();
+
+ // Only PS states are tracked for IMS.
+ imsServiceState.addNetworkRegistrationInfo(imsPsWwanRegInfo);
+ imsServiceState.addNetworkRegistrationInfo(imsPsWlanRegInfo);
+
+ // Voice reg state in this case is whether or not IMS is registered.
+ imsServiceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
+ imsServiceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
+ imsServiceState.setIwlanPreferred(true);
+ doReturn(imsServiceState).when(mImsPhone).getServiceState();
+
+ replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);
+
+ ServiceState serviceState = new ServiceState();
+
+ NetworkRegistrationInfo csWwanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_UNKNOWN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .build();
+
+ NetworkRegistrationInfo psWwanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .build();
+
+ NetworkRegistrationInfo psWlanRegInfo = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .build();
+
+ serviceState.addNetworkRegistrationInfo(csWwanRegInfo);
+ serviceState.addNetworkRegistrationInfo(psWwanRegInfo);
+ serviceState.addNetworkRegistrationInfo(psWlanRegInfo);
+ // No CSFB, voice is OOS for LTE only attach
+ serviceState.setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
+ serviceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
+ serviceState.setIwlanPreferred(true);
+
+ mSST.mSS = serviceState;
+ mPhoneUT.mSST = mSST;
+
+ ServiceState mergedServiceState = mPhoneUT.getServiceState();
+
+ assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getVoiceRegState());
+ assertEquals(ServiceState.STATE_IN_SERVICE, mergedServiceState.getDataRegState());
+ assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mergedServiceState.getDataNetworkType());
+ }
+
@Test
@SmallTest
public void testGetSubscriberIdForGsmPhone() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
index 51aa5d0..5d69ab6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
@@ -20,7 +20,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
@@ -55,7 +54,7 @@
private static final String US_MCC = "310";
private static final String LIECHTENSTEIN_MCC = "295";
- private static final String BOGUS_MCC = "001";
+ private static final String TEST_CELL_MCC = "001";
private static final String FAKE_MNC = "123";
@@ -284,14 +283,14 @@
throws Exception {
mLocaleTracker.updateOperatorNumeric("");
sendOperatorLost();
- verify(mNitzStateMachine, times(1)).handleNetworkCountryCodeUnavailable();
+ verify(mNitzStateMachine, times(1)).handleCountryUnavailable();
}
@Test
@SmallTest
- public void updateOperatorNumeric_BogusNetwork_shouldHandleNetworkCountryCodeSet()
+ public void updateOperatorNumeric_TestNetwork_shouldHandleNetworkCountryCodeSet()
throws Exception {
- mLocaleTracker.updateOperatorNumeric(BOGUS_MCC + FAKE_MNC);
- verify(mNitzStateMachine, times(1)).handleNetworkCountryCodeSet(anyBoolean());
+ mLocaleTracker.updateOperatorNumeric(TEST_CELL_MCC + FAKE_MNC);
+ verify(mNitzStateMachine, times(1)).handleCountryDetected("");
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
index d195c2e..a2cfea0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
@@ -16,33 +16,51 @@
package com.android.internal.telephony;
-import android.test.AndroidTestCase;
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
import android.test.suitebuilder.annotation.SmallTest;
-import org.junit.Ignore;
+import androidx.test.InstrumentationRegistry;
+
+import com.android.internal.telephony.MccTable.MccMnc;
+
+import org.junit.Test;
import java.util.Locale;
-// TODO try using InstrumentationRegistry.getContext() instead of the default
-// AndroidTestCase context
-public class MccTableTest extends AndroidTestCase {
- private final static String LOG_TAG = "GSM";
+public class MccTableTest {
@SmallTest
- @Ignore
- public void testCountryCode() throws Exception {
- assertEquals("lu", MccTable.countryCodeForMcc(270));
- assertEquals("gr", MccTable.countryCodeForMcc(202));
- assertEquals("fk", MccTable.countryCodeForMcc(750));
- assertEquals("mg", MccTable.countryCodeForMcc(646));
- assertEquals("us", MccTable.countryCodeForMcc(314));
- assertEquals("", MccTable.countryCodeForMcc(300)); // mcc not defined, hence default
- assertEquals("", MccTable.countryCodeForMcc(0)); // mcc not defined, hence default
- assertEquals("", MccTable.countryCodeForMcc(2000)); // mcc not defined, hence default
+ @Test
+ public void testCountryCodeForMcc() throws Exception {
+ checkMccLookupWithNoMnc("lu", 270);
+ checkMccLookupWithNoMnc("gr", 202);
+ checkMccLookupWithNoMnc("fk", 750);
+ checkMccLookupWithNoMnc("mg", 646);
+ checkMccLookupWithNoMnc("us", 314);
+ checkMccLookupWithNoMnc("", 300); // mcc not defined, hence default
+ checkMccLookupWithNoMnc("", 0); // mcc not defined, hence default
+ checkMccLookupWithNoMnc("", 2000); // mcc not defined, hence default
+ }
+
+ private void checkMccLookupWithNoMnc(String expectedCountryIsoCode, int mcc) {
+ assertEquals(expectedCountryIsoCode, MccTable.countryCodeForMcc(mcc));
+ assertEquals(expectedCountryIsoCode, MccTable.countryCodeForMcc(mcc));
+ assertEquals(expectedCountryIsoCode, MccTable.countryCodeForMcc("" + mcc));
+ assertEquals(expectedCountryIsoCode,
+ MccTable.geoCountryCodeForMccMnc(new MccMnc("" + mcc, "999")));
}
@SmallTest
- @Ignore
+ @Test
+ public void testGeoCountryCodeForMccMnc() throws Exception {
+ // This test is possibly fragile as this data is configurable.
+ assertEquals("gu", MccTable.geoCountryCodeForMccMnc(new MccMnc("310", "370")));
+ }
+
+ @SmallTest
+ @Test
public void testLang() throws Exception {
assertEquals("en", MccTable.defaultLanguageForMcc(311));
assertEquals("de", MccTable.defaultLanguageForMcc(232));
@@ -54,7 +72,7 @@
}
@SmallTest
- @Ignore
+ @Test
public void testLang_India() throws Exception {
assertEquals("en", MccTable.defaultLanguageForMcc(404));
assertEquals("en", MccTable.defaultLanguageForMcc(405));
@@ -62,7 +80,7 @@
}
@SmallTest
- @Ignore
+ @Test
public void testLocale() throws Exception {
assertEquals(Locale.forLanguageTag("en-CA"),
MccTable.getLocaleFromMcc(getContext(), 302, null));
@@ -78,8 +96,12 @@
MccTable.getLocaleFromMcc(getContext(), 466, null));
}
+ private Context getContext() {
+ return InstrumentationRegistry.getContext();
+ }
+
@SmallTest
- @Ignore
+ @Test
public void testSmDigits() throws Exception {
assertEquals(3, MccTable.smallestDigitsMccForMnc(312));
assertEquals(2, MccTable.smallestDigitsMccForMnc(430));
diff --git a/src/java/com/android/internal/telephony/test/ModelInterpreter.java b/tests/telephonytests/src/com/android/internal/telephony/ModelInterpreter.java
similarity index 100%
rename from src/java/com/android/internal/telephony/test/ModelInterpreter.java
rename to tests/telephonytests/src/com/android/internal/telephony/ModelInterpreter.java
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
index 1b74a6b..c9a8f11 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineImplTest.java
@@ -25,6 +25,7 @@
import static com.android.internal.telephony.NitzStateMachineTestSupport.UNIQUE_US_ZONE_SCENARIO2;
import static com.android.internal.telephony.NitzStateMachineTestSupport.UNITED_KINGDOM_SCENARIO;
import static com.android.internal.telephony.NitzStateMachineTestSupport.US_COUNTRY_DEFAULT_ZONE_ID;
+import static com.android.internal.telephony.NitzStateMachineTestSupport.createEmptyTimeSuggestion;
import static com.android.internal.telephony.NitzStateMachineTestSupport.createTimeSuggestionFromNitzSignal;
import static org.junit.Assert.assertEquals;
@@ -102,6 +103,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -221,6 +223,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -254,6 +257,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// A valid NITZ signal for the non-default zone should still be correctly detected.
@@ -268,6 +272,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// Demonstrate what happens with a bogus NITZ for NZ: because the default zone is boosted
@@ -285,6 +290,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(expectedTimeZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
}
@@ -318,6 +324,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// A valid NITZ signal for a different zone should also be correctly detected.
@@ -332,6 +339,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
// Demonstrate what happens with a bogus NITZ for US: because the default zone is not
@@ -346,8 +354,9 @@
.verifyNothingWasSetAndReset();
// Check NitzStateMachine state.
- assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
}
@@ -374,6 +383,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -399,6 +409,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -423,6 +434,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -432,6 +444,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -455,6 +468,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode());
@@ -465,6 +479,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -490,6 +505,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(goodNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -498,6 +514,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(goodNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -520,6 +537,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving an NITZ signal.
script.nitzReceived(goodNitzSignal);
@@ -534,6 +552,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(goodNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -568,6 +587,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -576,6 +596,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -606,6 +627,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving an NITZ signal.
script.nitzReceived(badNitzSignal);
@@ -618,6 +640,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -651,6 +674,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the country code becoming known.
script.countryReceived(scenario.getNetworkCountryIsoCode())
@@ -661,6 +685,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -692,6 +717,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving an NITZ signal.
script.nitzReceived(badNitzSignal);
@@ -704,6 +730,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(badNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -740,6 +767,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(emulatorNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(emulatorTimeZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -759,6 +787,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate receiving the NITZ signal.
TimestampedValue<NitzData> nitzSignal =
@@ -772,6 +801,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(expectedZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -797,6 +827,7 @@
// Check NitzStateMachine state.
assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// The time zone should be set (but the country is not valid so it's unlikely to be
// correct).
@@ -805,6 +836,7 @@
// Check NitzStateMachine state.
assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(nitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(expectedZoneId, mNitzStateMachine.getSavedTimeZoneId());
}
@Test
@@ -842,7 +874,9 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(preflightNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Boarded flight: Airplane mode turned on / time zone detection still enabled.
// The NitzStateMachineImpl must lose all state and stop having an opinion about time zone.
@@ -854,11 +888,14 @@
script.toggleAirplaneMode(true);
// Check state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Verify there's no time zone opinion by toggling auto time zone off and on.
+ PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
script.toggleTimeZoneDetectionEnabled(false)
- .verifyNothingWasSetAndReset()
+ .verifyOnlyTimeWasSuggestedAndReset(emptyTimeSuggestion)
.toggleTimeZoneDetectionEnabled(true)
.verifyNothingWasSetAndReset();
@@ -878,7 +915,9 @@
.verifyNothingWasSetAndReset();
// Check the state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Post flight: Device has moved and receives new signals.
@@ -903,7 +942,9 @@
scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(postFlightNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
/**
@@ -944,19 +985,25 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(initialNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate losing the network. The NitzStateMachineImpl must lose all NITZ state and stop
// having an opinion about time zone.
- script.networkUnavailable()
- .verifyNothingWasSetAndReset();
+ script.networkUnavailable();
+
+ PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
+ script.verifyOnlyTimeWasSuggestedAndReset(emptyTimeSuggestion);
// Simulate the passage of time and update the device realtime clock.
scenario.incrementTime(timeStepMillis);
script.incrementTime(timeStepMillis);
// Check state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Verify there's no time zone opinion by toggling auto time zone off and on.
script.toggleTimeZoneDetectionEnabled(false)
@@ -978,7 +1025,9 @@
.verifyNothingWasSetAndReset();
// Check the state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertNull(mNitzStateMachine.getSavedTimeZoneId());
// Simulate the passage of time and update the device realtime clock.
scenario.incrementTime(timeStepMillis);
@@ -996,7 +1045,9 @@
scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(finalNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
/**
@@ -1037,20 +1088,26 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(initialNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate losing the network. The NitzStateMachineImpl must lose all NITZ state but should
// retain country knowledge and so remain opinionated about time zone ID because the country
// is sufficient to detect time zone in the UK.
- script.networkUnavailable()
- .verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
+ script.networkUnavailable();
+
+ PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
+ script.verifyTimeSuggestedAndZoneSetAndReset(emptyTimeSuggestion, scenario.getTimeZoneId());
// Simulate the passage of time and update the device realtime clock.
scenario.incrementTime(timeStepMillis);
script.incrementTime(timeStepMillis);
// Check state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Verify there's a time zone opinion by toggling auto time zone off and on.
script.toggleTimeZoneDetectionEnabled(false)
@@ -1072,7 +1129,9 @@
.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
// Check the state that NitzStateMachine must expose.
+ assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertNull(mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
// Simulate the passage of time and update the device realtime clock.
scenario.incrementTime(timeStepMillis);
@@ -1090,7 +1149,9 @@
scenario.getTimeZoneId());
// Check state that NitzStateMachine must expose.
+ assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
assertEquals(finalNitzSignal.getValue(), mNitzStateMachine.getCachedNitzData());
+ assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
}
/**
@@ -1146,8 +1207,7 @@
}
Script countryReceived(String countryIsoCode) {
- mFakeDeviceState.networkCountryIsoForPhone = countryIsoCode;
- mNitzStateMachine.handleNetworkCountryCodeSet(true);
+ mNitzStateMachine.handleCountryDetected(countryIsoCode);
return this;
}
@@ -1318,8 +1378,10 @@
@Override
public void suggestDeviceTime(PhoneTimeSuggestion phoneTimeSuggestion) {
suggestedTime.set(phoneTimeSuggestion);
- // The fake time service just uses the latest suggestion.
- mFakeDeviceState.currentTimeMillis = phoneTimeSuggestion.getUtcTime().getValue();
+ if (phoneTimeSuggestion.getUtcTime() != null) {
+ // The fake time service just uses the latest suggestion.
+ mFakeDeviceState.currentTimeMillis = phoneTimeSuggestion.getUtcTime().getValue();
+ }
}
void commitState() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
index 02a0cc9..b9215ed 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NitzStateMachineTestSupport.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.fail;
import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
import android.icu.util.Calendar;
import android.icu.util.GregorianCalendar;
import android.icu.util.TimeZone;
@@ -214,7 +215,6 @@
public boolean ignoreNitz;
public int nitzUpdateDiffMillis;
public int nitzUpdateSpacingMillis;
- public String networkCountryIsoForPhone;
public long elapsedRealtime;
public long currentTimeMillis;
@@ -242,11 +242,6 @@
}
@Override
- public String getNetworkCountryIsoForPhone() {
- return networkCountryIsoForPhone;
- }
-
- @Override
public long elapsedRealtime() {
return elapsedRealtime;
}
@@ -276,10 +271,23 @@
return cal.getTimeInMillis();
}
+ public static PhoneTimeZoneSuggestion createEmptyTimeZoneSuggestion(int phoneId) {
+ return new PhoneTimeZoneSuggestion.Builder(phoneId)
+ .addDebugInfo("Test")
+ .build();
+ }
+
+ public static PhoneTimeSuggestion createEmptyTimeSuggestion(int phoneId) {
+ PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(phoneId);
+ timeSuggestion.addDebugInfo("Test");
+ return timeSuggestion;
+ }
+
public static PhoneTimeSuggestion createTimeSuggestionFromNitzSignal(
int phoneId, TimestampedValue<NitzData> nitzSignal) {
- PhoneTimeSuggestion timeSuggestion =
- new PhoneTimeSuggestion(phoneId, createTimeSignalFromNitzSignal(nitzSignal));
+ PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(phoneId);
+ timeSuggestion.setUtcTime(createTimeSignalFromNitzSignal(nitzSignal));
+ timeSuggestion.addDebugInfo("Test");
return timeSuggestion;
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
index 6f01a47..08e5a0a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
@@ -168,6 +168,7 @@
// Verify set system property being called.
verify(mMi).setMultiSimProperties(MODEM_COUNT_DUAL_MODEM);
+ verify(mMi).notifyPhoneFactoryOnMultiSimConfigChanged(any(), eq(MODEM_COUNT_DUAL_MODEM));
// Capture and verify registration notification.
verify(mHandler).sendMessageAtTime(captor.capture(), anyLong());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index a69a9a6..69c2ff7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -66,8 +66,8 @@
mAppOsMgr = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- mPhoneSubInfoControllerUT = new PhoneSubInfoController(mContext,
- new Phone[]{mPhone, mSecondPhone});
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[]{mPhone, mSecondPhone});
+ mPhoneSubInfoControllerUT = new PhoneSubInfoController(mContext);
setupMocksForTelephonyPermissions();
// TelephonyPermissions will query the READ_DEVICE_IDENTIFIERS op from AppOpManager to
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
index fe0e74f..0408253 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
@@ -17,12 +17,14 @@
package com.android.internal.telephony;
import static android.telephony.CarrierConfigManager.KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG;
+import static android.telephony.TelephonyManager.MODEM_COUNT_DUAL_MODEM;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
import static com.android.internal.telephony.PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS;
import static com.android.internal.telephony.PhoneSwitcher.EVENT_DATA_ENABLED_CHANGED;
+import static com.android.internal.telephony.PhoneSwitcher.EVENT_MULTI_SIM_CONFIG_CHANGED;
import static com.android.internal.telephony.PhoneSwitcher.EVENT_PRECISE_CALL_STATE_CHANGED;
import static org.junit.Assert.assertEquals;
@@ -54,10 +56,13 @@
import android.os.Messenger;
import android.telephony.PhoneCapability;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyRegistryManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.telephony.dataconnection.DataEnabledSettings;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -81,16 +86,14 @@
private static final int ACTIVE_PHONE_SWITCH = 1;
@Mock
- private ITelephonyRegistry.Stub mTelRegistryMock;
- @Mock
- private ITelephonyRegistry mTelRegistryInterfaceMock;
- @Mock
private CommandsInterface mCommandsInterface0;
@Mock
private CommandsInterface mCommandsInterface1;
@Mock
private Phone mPhone2; // mPhone as phone 1 is already defined in TelephonyTest.
@Mock
+ private DataEnabledSettings mDataEnabledSettings2;
+ @Mock
private Handler mActivePhoneSwitchHandler;
@Mock
private GsmCdmaCall mActiveCall;
@@ -106,14 +109,16 @@
CompletableFuture<Boolean> mFuturePhone;
private PhoneSwitcher mPhoneSwitcher;
- private IOnSubscriptionsChangedListener mSubChangedListener;
+ private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
private ConnectivityManager mConnectivityManager;
// The messenger of PhoneSwitcher used to receive network requests.
private Messenger mNetworkFactoryMessenger = null;
private int mDefaultDataSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private CommandsInterface[] mCommandsInterfaces;
private int[][] mSlotIndexToSubId;
private boolean[] mDataAllowed;
+ private int mActiveModemCount = 2;
+ private int mSupportedModemCount = 2;
+ private int mMaxDataAttachModemCount = 1;
@Before
public void setUp() throws Exception {
@@ -121,12 +126,13 @@
PhoneCapability phoneCapability = new PhoneCapability(1, 1, 0, null, false);
doReturn(phoneCapability).when(mPhoneConfigurationManager).getCurrentPhoneCapability();
- mServiceManagerMockedServices.put("telephony.registry", mTelRegistryMock);
- doReturn(mTelRegistryInterfaceMock).when(mTelRegistryMock).queryLocalInterface(any());
doReturn(Call.State.ACTIVE).when(mActiveCall).getState();
doReturn(Call.State.IDLE).when(mInactiveCall).getState();
doReturn(Call.State.HOLDING).when(mHoldingCall).getState();
+
+ replaceInstance(Phone.class, "mCi", mPhone, mCommandsInterface0);
+ replaceInstance(Phone.class, "mCi", mPhone2, mCommandsInterface1);
}
@After
@@ -140,9 +146,7 @@
@Test
@SmallTest
public void testRegister() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
- initialize(numPhones, maxActivePhones);
+ initialize();
// verify nothing has been done while there are no inputs
assertFalse("data allowed initially", mDataAllowed[0]);
@@ -314,9 +318,7 @@
@Test
@SmallTest
public void testPrioritization() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
- initialize(numPhones, maxActivePhones);
+ initialize();
addInternetNetworkRequest(null, 50);
setSlotIndexToSubId(0, 0);
@@ -347,9 +349,7 @@
@Test
@SmallTest
public void testHigherPriorityDefault() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
- initialize(numPhones, maxActivePhones);
+ initialize();
addInternetNetworkRequest(null, 50);
@@ -383,9 +383,7 @@
@Test
@SmallTest
public void testSetPreferredData() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
@@ -416,10 +414,8 @@
@Test
@SmallTest
public void testSetPreferredDataModemCommand() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
ACTIVE_PHONE_SWITCH, null);
mPhoneSwitcher.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
@@ -484,10 +480,8 @@
@Test
@SmallTest
public void testSetPreferredDataWithValidation() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
@@ -535,10 +529,8 @@
@Test
@SmallTest
public void testNonDefaultDataPhoneInCall() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
@@ -584,10 +576,8 @@
@Test
@SmallTest
public void testNetworkRequestOnNonDefaultData() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
@@ -607,14 +597,12 @@
@Test
@SmallTest
public void testEmergencyOverrideSuccessBeforeCallStarts() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
- setMsimDefaultDataSubId(numPhones, 1);
+ setMsimDefaultDataSubId(1);
clearInvocations(mMockRadioConfig);
// override the phone ID in prep for emergency call
@@ -623,20 +611,18 @@
processAllMessages();
verify(mFuturePhone).complete(true);
// Make sure the correct broadcast is sent out for the overridden phone ID
- verify(mTelRegistryInterfaceMock).notifyActiveDataSubIdChanged(eq(2));
+ verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));
}
@Test
@SmallTest
public void testEmergencyOverrideNoDdsChange() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
- setMsimDefaultDataSubId(numPhones, 1);
+ setMsimDefaultDataSubId(1);
clearInvocations(mMockRadioConfig);
// override the phone ID in prep for emergency call
@@ -652,17 +638,15 @@
@SmallTest
public void testEmergencyOverrideEndSuccess() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
- setMsimDefaultDataSubId(numPhones, 1);
+ setMsimDefaultDataSubId(1);
setAllPhonesInactive();
clearInvocations(mMockRadioConfig);
- clearInvocations(mTelRegistryInterfaceMock);
+ clearInvocations(mTelephonyRegistryManager);
// override the phone ID in prep for emergency call
mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
@@ -674,30 +658,28 @@
notifyPhoneAsInCall(mPhone2);
notifyPhoneAsInactive(mPhone2);
- clearInvocations(mTelRegistryInterfaceMock);
+ clearInvocations(mTelephonyRegistryManager);
// Verify that the DDS is successfully switched back after 1 second + base ECBM timeout
moveTimeForward(ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS + 1000);
processAllMessages();
verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
// Make sure the correct broadcast is sent out for the phone ID
- verify(mTelRegistryInterfaceMock).notifyActiveDataSubIdChanged(eq(1));
+ verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
}
@Test
@SmallTest
public void testEmergencyOverrideEcbmStartEnd() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
- setMsimDefaultDataSubId(numPhones, 1);
+ setMsimDefaultDataSubId(1);
setAllPhonesInactive();
clearInvocations(mMockRadioConfig);
- clearInvocations(mTelRegistryInterfaceMock);
+ clearInvocations(mTelephonyRegistryManager);
// override the phone ID in prep for emergency call
mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
@@ -718,10 +700,10 @@
processAllMessages();
verify(mMockRadioConfig, never()).setPreferredDataModem(eq(0), any());
// Make sure the correct broadcast is sent out for the phone ID
- verify(mTelRegistryInterfaceMock).notifyActiveDataSubIdChanged(eq(2));
+ verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(2));
// End ECBM
- clearInvocations(mTelRegistryInterfaceMock);
+ clearInvocations(mTelephonyRegistryManager);
ecbmMessage = getEcbmRegistration(mPhone2);
notifyEcbmEnd(mPhone2, ecbmMessage);
// Verify that the DDS is successfully switched back after 1 second.
@@ -729,24 +711,22 @@
processAllMessages();
verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
// Make sure the correct broadcast is sent out for the phone ID
- verify(mTelRegistryInterfaceMock).notifyActiveDataSubIdChanged(eq(1));
+ verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
}
@Test
@SmallTest
public void testEmergencyOverrideNoCallStart() throws Exception {
PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 500;
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
- setMsimDefaultDataSubId(numPhones, 1);
+ setMsimDefaultDataSubId(1);
setAllPhonesInactive();
clearInvocations(mMockRadioConfig);
- clearInvocations(mTelRegistryInterfaceMock);
+ clearInvocations(mTelephonyRegistryManager);
// override the phone ID in prep for emergency call
mPhoneSwitcher.overrideDefaultDataForEmergency(1, 1, mFuturePhone);
@@ -759,24 +739,22 @@
processAllMessages();
verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
// Make sure the correct broadcast is sent out for the phone ID
- verify(mTelRegistryInterfaceMock).notifyActiveDataSubIdChanged(eq(1));
+ verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
}
@Test
@SmallTest
public void testEmergencyOverrideMultipleOverrideRequests() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Phone 0 has sub 1, phone 1 has sub 2.
// Sub 1 is default data sub.
// Both are active subscriptions are active sub, as they are in both active slots.
- setMsimDefaultDataSubId(numPhones, 1);
+ setMsimDefaultDataSubId(1);
setAllPhonesInactive();
clearInvocations(mMockRadioConfig);
- clearInvocations(mTelRegistryInterfaceMock);
+ clearInvocations(mTelephonyRegistryManager);
// override the phone ID in prep for emergency call
LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
@@ -808,16 +786,14 @@
processAllMessages();
verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
// Make sure the correct broadcast is sent out for the phone ID
- verify(mTelRegistryInterfaceMock).notifyActiveDataSubIdChanged(eq(1));
+ verify(mTelephonyRegistryManager).notifyActiveDataSubIdChanged(eq(1));
}
@Test
@SmallTest
public void testSetPreferredDataCallback() throws Exception {
- final int numPhones = 2;
- final int maxActivePhones = 1;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
- initialize(numPhones, maxActivePhones);
+ initialize();
// Mark sub 2 as opportunistic.
doReturn(true).when(mSubscriptionController).isOpportunistic(2);
@@ -910,6 +886,36 @@
verify(mSetOpptDataCallback2).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
}
+
+ @Test
+ @SmallTest
+ public void testMultiSimConfigChange() throws Exception {
+ doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
+ mActiveModemCount = 1;
+ initialize();
+ sendPreferredDataSuccessResult(0);
+
+ // Phone 0 has sub 1, phone 1 has sub 2.
+ // Sub 1 is default data sub.
+ // Both are active subscriptions are active sub, as they are in both active slots.
+ setSlotIndexToSubId(0, 1);
+ setDefaultDataSubId(1);
+
+ setNumPhones(MODEM_COUNT_DUAL_MODEM, MODEM_COUNT_DUAL_MODEM);
+ AsyncResult result = new AsyncResult(null, MODEM_COUNT_DUAL_MODEM, null);
+ Message.obtain(mPhoneSwitcher, EVENT_MULTI_SIM_CONFIG_CHANGED, result).sendToTarget();
+ processAllMessages();
+
+ verify(mPhone2).registerForEmergencyCallToggle(any(), anyInt(), any());
+ verify(mPhone2).registerForPreciseCallStateChanged(any(), anyInt(), any());
+ verify(mDataEnabledSettings2).registerForDataEnabledChanged(any(), anyInt(), any());
+
+ clearInvocations(mMockRadioConfig);
+ setSlotIndexToSubId(1, 2);
+ setDefaultDataSubId(2);
+ verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
+ }
+
/* Private utility methods start here */
private void setAllPhonesInactive() {
@@ -941,6 +947,7 @@
private void notifyDataEnabled(boolean dataEnabled) {
doReturn(dataEnabled).when(mDataEnabledSettings).isDataEnabled(anyInt());
+ doReturn(dataEnabled).when(mDataEnabledSettings2).isDataEnabled(anyInt());
mPhoneSwitcher.sendEmptyMessage(EVENT_DATA_ENABLED_CHANGED);
processAllMessages();
}
@@ -982,13 +989,13 @@
processAllMessages();
}
- private void setMsimDefaultDataSubId(int numPhones, int defaultDataSub) throws Exception {
- for (int i = 0; i < numPhones; i++) {
+ private void setMsimDefaultDataSubId(int defaultDataSub) throws Exception {
+ for (int i = 0; i < mActiveModemCount; i++) {
setSlotIndexToSubId(i, i + 1);
}
setDefaultDataSubId(defaultDataSub);
NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
- for (int i = 0; i < numPhones; i++) {
+ for (int i = 0; i < mActiveModemCount; i++) {
if (defaultDataSub == (i + 1)) {
// sub id is always phoneId+1 for testing
assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(internetRequest, i));
@@ -1004,54 +1011,52 @@
processAllMessages();
}
- private void initialize(int numPhones, int maxActivePhones) throws Exception {
+ private void initialize() throws Exception {
mContextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
sNetworkAttributes);
- setNumPhones(numPhones);
+ setNumPhones(mActiveModemCount, mSupportedModemCount);
initializeSubControllerMock();
- initializeCommandInterfacesMock(numPhones);
+ initializeCommandInterfacesMock();
initializeTelRegistryMock();
initializeConnManagerMock();
- mPhoneSwitcher = new PhoneSwitcher(maxActivePhones, numPhones,
- mContext, mSubscriptionController, Looper.myLooper(),
- mTelRegistryMock, mCommandsInterfaces, mPhones);
+ mPhoneSwitcher = new PhoneSwitcher(mMaxDataAttachModemCount, mContext, Looper.myLooper());
processAllMessages();
- verify(mTelRegistryMock).addOnSubscriptionsChangedListener(
- eq(mContext.getOpPackageName()), any());
+ verify(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
}
/**
* Certain variables needs initialized depending on number of phones.
*/
- private void setNumPhones(int numPhones) {
- mDataAllowed = new boolean[numPhones];
- mSlotIndexToSubId = new int[numPhones][];
+ private void setNumPhones(int activeModemCount, int supportedModemCount) throws Exception {
+ mDataAllowed = new boolean[supportedModemCount];
+ mSlotIndexToSubId = new int[supportedModemCount][];
doReturn(0).when(mPhone).getPhoneId();
doReturn(1).when(mPhone2).getPhoneId();
doReturn(true).when(mPhone2).isUserDataEnabled();
- doReturn(mDataEnabledSettings).when(mPhone2).getDataEnabledSettings();
- for (int i = 0; i < numPhones; i++) {
+ doReturn(mDataEnabledSettings2).when(mPhone2).getDataEnabledSettings();
+ for (int i = 0; i < supportedModemCount; i++) {
mSlotIndexToSubId[i] = new int[1];
mSlotIndexToSubId[i][0] = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
- doReturn(numPhones).when(mTelephonyManager).getPhoneCount();
- doReturn(numPhones).when(mTelephonyManager).getActiveModemCount();
- if (numPhones == 1) {
- mCommandsInterfaces = new CommandsInterface[] {mCommandsInterface0};
- mPhones = new Phone[] {mPhone};
- } else if (numPhones == 2) {
- mCommandsInterfaces =
- new CommandsInterface[] {mCommandsInterface0, mCommandsInterface1};
- mPhones = new Phone[] {mPhone, mPhone2};
+ doReturn(activeModemCount).when(mTelephonyManager).getPhoneCount();
+ doReturn(activeModemCount).when(mTelephonyManager).getActiveModemCount();
+ doReturn(supportedModemCount).when(mTelephonyManager).getSupportedModemCount();
+
+ if (activeModemCount == 1) {
+ mPhones = new Phone[]{mPhone};
+ } else if (activeModemCount == 2) {
+ mPhones = new Phone[]{mPhone, mPhone2};
}
+
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
}
- private void initializeCommandInterfacesMock(int numPhones) {
+ private void initializeCommandInterfacesMock() {
// Tell PhoneSwitcher that radio is on.
doAnswer(invocation -> {
Handler handler = (Handler) invocation.getArguments()[0];
@@ -1067,7 +1072,7 @@
return null;
}).when(mCommandsInterface0).setDataAllowed(anyBoolean(), any());
- if (numPhones == 2) {
+ if (mSupportedModemCount > 1) {
doAnswer(invocation -> {
mDataAllowed[1] = (boolean) invocation.getArguments()[0];
return null;
@@ -1081,12 +1086,12 @@
*/
private void initializeTelRegistryMock() throws Exception {
doAnswer(invocation -> {
- IOnSubscriptionsChangedListener subChangedListener =
- (IOnSubscriptionsChangedListener) invocation.getArguments()[1];
+ SubscriptionManager.OnSubscriptionsChangedListener subChangedListener =
+ (SubscriptionManager.OnSubscriptionsChangedListener) invocation.getArguments()[0];
mSubChangedListener = subChangedListener;
mSubChangedListener.onSubscriptionsChanged();
return null;
- }).when(mTelRegistryMock).addOnSubscriptionsChangedListener(any(), any());
+ }).when(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
}
/**
@@ -1209,4 +1214,4 @@
mNetworkFactoryMessenger.send(message);
processAllMessages();
}
-}
\ No newline at end of file
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ProxyControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ProxyControllerTest.java
new file mode 100644
index 0000000..128e6d8
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/ProxyControllerTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import static com.android.internal.telephony.ProxyController.EVENT_MULTI_SIM_CONFIG_CHANGED;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.verify;
+
+import android.os.Handler;
+import android.os.Message;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class ProxyControllerTest extends TelephonyTest {
+ @Mock
+ Phone mPhone2;
+
+ ProxyController mProxyController;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ replaceInstance(ProxyController.class, "sProxyController", null, null);
+ mProxyController = ProxyController.getInstance(mContext);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ // Restore system properties.
+ super.tearDown();
+ }
+
+ @Test
+ @SmallTest
+ public void testMultiSimConfigChange() throws Exception {
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(int.class);
+
+ // Switch to dual-SIM and send multi sim config change callback.
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mPhone2});
+ Message.obtain(mProxyController.mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED).sendToTarget();
+ processAllMessages();
+ verify(mPhone2).registerForRadioCapabilityChanged(any(), anyInt(), any());
+
+ // Switch to single-SIM and verify there's at least no crash.
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone});
+ Message.obtain(mProxyController.mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED).sendToTarget();
+ processAllMessages();
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 3874261..fda30f5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -119,12 +119,14 @@
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityNr;
import android.telephony.CellIdentityTdscdma;
import android.telephony.CellIdentityWcdma;
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
+import android.telephony.CellInfoNr;
import android.telephony.CellInfoTdscdma;
import android.telephony.CellInfoWcdma;
import android.telephony.CellSignalStrengthCdma;
@@ -205,6 +207,7 @@
private static final int MNC = 260;
private static final String MNC_STR = "260";
private static final int NETWORK_ID = 65534;
+ private static final int NRARFCN = 3279165;
private static final int PCI = 503;
private static final int PSC = 500;
private static final int RIL_TIMESTAMP_TYPE_OEM_RIL = 3;
@@ -1563,6 +1566,47 @@
}
@Test
+ public void testConvertHalCellInfoList_1_4ForNr() {
+ android.hardware.radio.V1_4.CellInfoNr cellinfo =
+ new android.hardware.radio.V1_4.CellInfoNr();
+ cellinfo.cellidentity.nci = CI;
+ cellinfo.cellidentity.pci = PCI;
+ cellinfo.cellidentity.tac = TAC;
+ cellinfo.cellidentity.nrarfcn = NRARFCN;
+ cellinfo.cellidentity.mcc = MCC_STR;
+ cellinfo.cellidentity.mnc = MNC_STR;
+ cellinfo.cellidentity.operatorNames.alphaLong = ALPHA_LONG;
+ cellinfo.cellidentity.operatorNames.alphaShort = ALPHA_SHORT;
+ cellinfo.signalStrength.ssRsrp = -RSRP;
+ cellinfo.signalStrength.ssRsrq = -RSRQ;
+ cellinfo.signalStrength.ssSinr = SIGNAL_NOISE_RATIO;
+ cellinfo.signalStrength.csiRsrp = -RSRP;
+ cellinfo.signalStrength.csiRsrq = -RSRQ;
+ cellinfo.signalStrength.csiSinr = SIGNAL_NOISE_RATIO;
+
+ android.hardware.radio.V1_4.CellInfo record = new android.hardware.radio.V1_4.CellInfo();
+ record.info.nr(cellinfo);
+
+ ArrayList<android.hardware.radio.V1_4.CellInfo> records = new ArrayList<>();
+ records.add(record);
+
+ ArrayList<CellInfo> ret = RIL.convertHalCellInfoList_1_4(records);
+
+ CellInfoNr cellInfoNr = (CellInfoNr) ret.get(0);
+ CellIdentityNr cellIdentityNr = (CellIdentityNr) cellInfoNr.getCellIdentity();
+ CellSignalStrengthNr signalStrengthNr =
+ (CellSignalStrengthNr) cellInfoNr.getCellSignalStrength();
+
+ CellIdentityNr expectedCellIdentity = new CellIdentityNr(PCI, TAC, NRARFCN, MCC_STR,
+ MNC_STR, CI, ALPHA_LONG, ALPHA_SHORT);
+ CellSignalStrengthNr expectedSignalStrength = new CellSignalStrengthNr(-RSRP, -RSRQ,
+ SIGNAL_NOISE_RATIO, -RSRP, -RSRQ, SIGNAL_NOISE_RATIO);
+
+ assertEquals(expectedCellIdentity, cellIdentityNr);
+ assertEquals(expectedSignalStrength, signalStrengthNr);
+ }
+
+ @Test
public void testConvertDataCallResult() {
// Test V1.0 SetupDataCallResult
android.hardware.radio.V1_0.SetupDataCallResult result10 =
@@ -1822,7 +1866,6 @@
}
@Test
- @FlakyTest
public void testSetupDataCall() throws Exception {
DataProfile dp = new DataProfile.Builder()
.setProfileId(PROFILE_ID)
@@ -1866,7 +1909,9 @@
assertEquals(APN_ENABLED, dpi.enabled);
assertEquals(SUPPORTED_APNT_YPES_BITMAK, dpi.supportedApnTypesBitmap);
assertEquals(ROAMING_PROTOCOL, ApnSetting.getProtocolIntFromString(dpi.protocol));
- assertEquals(BEARER_BITMASK, dpi.bearerBitmap);
+ assertEquals(
+ BEARER_BITMASK,
+ ServiceState.convertBearerBitmaskToNetworkTypeBitmask(dpi.bearerBitmap >> 1));
assertEquals(MTU, dpi.mtu);
}
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
similarity index 99%
rename from src/java/com/android/internal/telephony/test/SimulatedCommands.java
rename to tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
index db581b2..261b60e 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java
@@ -46,6 +46,7 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
import android.telephony.emergency.EmergencyNumber;
@@ -1179,6 +1180,14 @@
}
}
+ // Store different cids to simulate concurrent IMS and default data calls
+ if ((dataProfile.getSupportedApnTypesBitmask() & ApnSetting.TYPE_IMS)
+ == ApnSetting.TYPE_IMS) {
+ mSetupDataCallResult.cid = 0;
+ } else {
+ mSetupDataCallResult.cid = 1;
+ }
+
DataCallResponse response = RIL.convertDataCallResult(mSetupDataCallResult);
if (mDcSuccess) {
resultSuccess(result, response);
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
similarity index 99%
rename from src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
rename to tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
index c550f2c..f030a40 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommandsVerifier.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
@@ -1127,7 +1127,7 @@
}
@Override
- public void sendCDMAFeatureCode(String FeatureCode, Message response) {
+ public void sendCDMAFeatureCode(String featureCode, Message response) {
}
@@ -1260,7 +1260,7 @@
}
@Override
- public void iccOpenLogicalChannel(String AID, int p2, Message response) {
+ public void iccOpenLogicalChannel(String aid, int p2, Message response) {
}
diff --git a/src/java/com/android/internal/telephony/test/SimulatedGsmCallState.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedGsmCallState.java
similarity index 100%
rename from src/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
rename to tests/telephonytests/src/com/android/internal/telephony/SimulatedGsmCallState.java
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
index ce3281d..75b3534 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
@@ -97,8 +97,6 @@
doReturn(1).when(mProxyController).getMaxRafSupported();
mContextFixture.putIntArrayResource(com.android.internal.R.array.sim_colors, new int[]{5});
-
- mSubscriptionControllerUT.updatePhonesAvailability(new Phone[] {mPhone});
}
@After
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionMonitorTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionMonitorTest.java
deleted file mode 100644
index 215bb16..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionMonitorTest.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import android.content.Context;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.telephony.Rlog;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.internal.telephony.mocks.SubscriptionControllerMock;
-import com.android.internal.telephony.mocks.TelephonyRegistryMock;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-public class SubscriptionMonitorTest extends AndroidTestCase {
- private final static String LOG_TAG = "SubscriptionMonitorTest";
-
- static void failAndStack(String str) {
- fail(str + "\n" + SubscriptionMonitorTest.stack());
- }
-
- static String stack() {
- StringBuilder sb = new StringBuilder();
- for(StackTraceElement e : Thread.currentThread().getStackTrace()) {
- sb.append(e.toString()).append("\n");
- }
- return sb.toString();
- }
-
- private static class TestHandler extends Handler {
- public final static int SUBSCRIPTION_CHANGED = 1;
- public final static int IN_IDLE = 2;
-
- HandlerThread handlerThread;
-
- public TestHandler(Looper looper) {
- super(looper);
- }
-
- public void die() {
- if(handlerThread != null) {
- handlerThread.quit();
- handlerThread = null;
- }
- }
-
- public void blockTilIdle() {
- Object lock = new Object();
- synchronized (lock) {
- Message msg = this.obtainMessage(IN_IDLE, lock);
- msg.sendToTarget();
- try {
- lock.wait();
- } catch (InterruptedException e) {}
- }
- }
-
- public static TestHandler makeHandler() {
- final HandlerThread handlerThread = new HandlerThread("TestHandler");
- handlerThread.start();
- final TestHandler result = new TestHandler(handlerThread.getLooper());
- result.handlerThread = handlerThread;
- return result;
- }
-
- private boolean objectEquals(Object o1, Object o2) {
- if (o1 == null) return (o2 == null);
- return o1.equals(o2);
- }
-
- private void failAndStack(String str) {
- SubscriptionMonitorTest.failAndStack(str);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SUBSCRIPTION_CHANGED: {
- AsyncResult ar = (AsyncResult)(msg.obj);
- if (objectEquals(ar.userObj, mSubscriptionChangedObject.get()) == false) {
- failAndStack("Subscription Changed object is incorrect!");
- }
- mSubscriptionChangedCount.incrementAndGet();
- Rlog.d(LOG_TAG, "SUBSCRIPTION_CHANGED, inc to " +
- mSubscriptionChangedCount.get());
- break;
- }
- case IN_IDLE: {
- Object lock = msg.obj;
- synchronized (lock) {
- lock.notify();
- }
- break;
- }
- }
- }
-
- private final AtomicInteger mSubscriptionChangedCount = new AtomicInteger(0);
- private final AtomicReference<Object> mSubscriptionChangedObject =
- new AtomicReference<Object>();
-
- public void reset() {
- mSubscriptionChangedCount.set(0);
- mSubscriptionChangedObject.set(null);
- }
-
- public void setSubscriptionChangedObject(Object o) {
- mSubscriptionChangedObject.set(o);
- }
-
- public int getSubscriptionChangedCount() {
- return mSubscriptionChangedCount.get();
- }
- }
-
- /**
- * Register and unregister normally.
- * Verify register worked by causing an event.
- * Verify unregister by causing another event.
- */
- @SmallTest
- public void testRegister() throws Exception {
- final int numPhones = 2;
- final ContextFixture contextFixture = new ContextFixture();
- final Context context = contextFixture.getTestDouble();
- ITelephonyRegistry.Stub telRegistry = new TelephonyRegistryMock();
- SubscriptionControllerMock subController =
- new SubscriptionControllerMock(context, telRegistry, numPhones);
-
- SubscriptionMonitor testedSubMonitor =
- new SubscriptionMonitor(telRegistry, context, subController, numPhones);
-
- TestHandler testHandler = TestHandler.makeHandler();
- Object subChangedObject = new Object();
- testHandler.setSubscriptionChangedObject(subChangedObject);
-
- // try events before registering
- subController.setSlotSubId(0, 0);
-
- if (testHandler.getSubscriptionChangedCount() != 0) {
- fail("pretest of SubscriptionChangedCount");
- }
-
- testedSubMonitor.registerForSubscriptionChanged(0, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
- testHandler.blockTilIdle();
-
- if (testHandler.getSubscriptionChangedCount() != 1) {
- fail("test1 of SubscriptionChangedCount");
- }
-
- subController.setSlotSubId(0, 1);
- testHandler.blockTilIdle();
-
- if (testHandler.getSubscriptionChangedCount() != 2) {
- fail("test2 of SubscriptionChangedCount");
- }
-
- subController.setSlotSubId(0, 0);
- testHandler.blockTilIdle();
-
- if (testHandler.getSubscriptionChangedCount() != 3) {
- fail("test3 of SubscriptionChangedCount, " +
- testHandler.getSubscriptionChangedCount() + " vs 3");
- }
-
- testedSubMonitor.unregisterForSubscriptionChanged(0, testHandler);
-
- subController.setSlotSubId(0, 1);
- testHandler.blockTilIdle();
-
- if (testHandler.getSubscriptionChangedCount() != 3) {
- fail("test4 of SubscriptionChangedCount, " +
- testHandler.getSubscriptionChangedCount() + " vs 3");
- }
-
- testHandler.die();
- }
-
- /**
- * Bad register/unregisters
- *
- * Try phoneId that doesn't exist.
- * Cause an event and verify don't get notified.
- * Try to unregister multiple times.
- */
- @SmallTest
- public void testBadRegister() throws Exception {
- final int numPhones = 2;
- final ContextFixture contextFixture = new ContextFixture();
- final Context context = contextFixture.getTestDouble();
- ITelephonyRegistry.Stub telRegistry = new TelephonyRegistryMock();
- SubscriptionControllerMock subController =
- new SubscriptionControllerMock(context, telRegistry, numPhones);
-
- SubscriptionMonitor testedSubMonitor =
- new SubscriptionMonitor(telRegistry, context, subController, numPhones);
-
- TestHandler testHandler = TestHandler.makeHandler();
- Object subChangedObject = new Object();
- testHandler.setSubscriptionChangedObject(subChangedObject);
-
- try {
- testedSubMonitor.registerForSubscriptionChanged(-1, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
- fail("IllegalArgumentException expected with bad phoneId");
- } catch (IllegalArgumentException e) {}
- try {
- testedSubMonitor.registerForSubscriptionChanged(numPhones, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
- fail("IllegalArgumentException expected with bad phoneId");
- } catch (IllegalArgumentException e) {}
-
- subController.setSlotSubId(0, 0);
-
- if (testHandler.getSubscriptionChangedCount() != 0) {
- fail("getSubscriptionChangedCount reported non-zero!");
- }
-
- testHandler.die();
- }
-
- /**
- * Try to force spurious notifications - register/unregister in tight loop with
- * events happening in the unregistered gap.
- */
- @SmallTest
- public void testSpuriousNotifications() throws Exception {
- final int numPhones = 2;
- final ContextFixture contextFixture = new ContextFixture();
- final Context context = contextFixture.getTestDouble();
- ITelephonyRegistry.Stub telRegistry = new TelephonyRegistryMock();
- SubscriptionControllerMock subController =
- new SubscriptionControllerMock(context, telRegistry, numPhones);
-
- SubscriptionMonitor testedSubMonitor =
- new SubscriptionMonitor(telRegistry, context, subController, numPhones);
-
- TestHandler testHandler = TestHandler.makeHandler();
- Object subChangedObject = new Object();
- testHandler.setSubscriptionChangedObject(subChangedObject);
-
- final int PHONE_ID = 0;
- final int FIRST_SUB_ID = 0;
- final int SECOND_SUB_ID = 1;
-
- testedSubMonitor.registerForSubscriptionChanged(PHONE_ID, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
- final int LOOP_COUNT = 1000;
- for (int i = 0; i < LOOP_COUNT; i++) {
- testedSubMonitor.unregisterForSubscriptionChanged(PHONE_ID, testHandler);
-
- subController.setSlotSubId(PHONE_ID, FIRST_SUB_ID);
- subController.setSlotSubId(PHONE_ID, SECOND_SUB_ID);
-
- testedSubMonitor.registerForSubscriptionChanged(PHONE_ID, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
- }
- testHandler.blockTilIdle();
-
- // should get one for every registration
- if (testHandler.getSubscriptionChangedCount() != 1 + LOOP_COUNT) {
- fail("getSubscriptionChangedCount reported " +
- testHandler.getSubscriptionChangedCount() + " != " + (1 + LOOP_COUNT));
- }
-
- testHandler.die();
- }
-
- /**
- * Test duplicate registrations - both should survive
- * Also test duplicate unreg - shouldn't crash..
- */
- @SmallTest
- public void testMultiRegUnregistration() throws Exception {
- final int numPhones = 2;
- final ContextFixture contextFixture = new ContextFixture();
- final Context context = contextFixture.getTestDouble();
- ITelephonyRegistry.Stub telRegistry = new TelephonyRegistryMock();
- SubscriptionControllerMock subController =
- new SubscriptionControllerMock(context, telRegistry, numPhones);
-
- SubscriptionMonitor testedSubMonitor =
- new SubscriptionMonitor(telRegistry, context, subController, numPhones);
-
- TestHandler testHandler = TestHandler.makeHandler();
- Object subChangedObject = new Object();
- testHandler.setSubscriptionChangedObject(subChangedObject);
-
- final int PHONE_ID = 0;
- final int FIRST_SUB_ID = 0;
- final int SECOND_SUB_ID = 1;
-
- testedSubMonitor.registerForSubscriptionChanged(PHONE_ID, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
- testedSubMonitor.registerForSubscriptionChanged(PHONE_ID, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
-
- subController.setSlotSubId(PHONE_ID, FIRST_SUB_ID);
- subController.setSlotSubId(PHONE_ID, SECOND_SUB_ID);
-
- testHandler.blockTilIdle();
-
- // should get 1 for each registration and 4 for the two events
- if (testHandler.getSubscriptionChangedCount() != 6) {
- fail("getSubscriptionChangedCount reported " +
- testHandler.getSubscriptionChangedCount() + " != 6");
- }
-
- testedSubMonitor.unregisterForSubscriptionChanged(PHONE_ID, testHandler);
- testedSubMonitor.unregisterForSubscriptionChanged(PHONE_ID, testHandler);
-
- testHandler.die();
- }
-
- /**
- * Try event flood while registered - verify receive all.
- */
- @SmallTest
- public void testEventFloodNotifications() throws Exception {
- final int numPhones = 2;
- final ContextFixture contextFixture = new ContextFixture();
- final Context context = contextFixture.getTestDouble();
- ITelephonyRegistry.Stub telRegistry = new TelephonyRegistryMock();
- SubscriptionControllerMock subController =
- new SubscriptionControllerMock(context, telRegistry, numPhones);
-
- SubscriptionMonitor testedSubMonitor =
- new SubscriptionMonitor(telRegistry, context, subController, numPhones);
-
- TestHandler testHandler = TestHandler.makeHandler();
- Object subChangedObject = new Object();
- testHandler.setSubscriptionChangedObject(subChangedObject);
-
- final int PHONE_ID = 0;
- final int FIRST_SUB_ID = 0;
- final int SECOND_SUB_ID = 1;
-
- testedSubMonitor.registerForSubscriptionChanged(PHONE_ID, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
-
- final int LOOP_COUNT = 1;
- for (int i = 0; i < LOOP_COUNT; i++) {
- subController.setSlotSubId(PHONE_ID, FIRST_SUB_ID);
- subController.setSlotSubId(PHONE_ID, SECOND_SUB_ID);
- }
- testHandler.blockTilIdle();
-
- // should get one for registration + 2 per loop
- if (testHandler.getSubscriptionChangedCount() != 1 + (2 * LOOP_COUNT)) {
- fail("getSubscriptionChangedCount reported " +
- testHandler.getSubscriptionChangedCount() + " != " + (1 + (2 * LOOP_COUNT)));
- }
-
- testHandler.die();
- }
-
- @SmallTest
- public void testNoSubChange() throws Exception {
- String TAG = "testNoSubChange";
- final int numPhones = 2;
- final ContextFixture contextFixture = new ContextFixture();
- final Context context = contextFixture.getTestDouble();
- ITelephonyRegistry.Stub telRegistry = new TelephonyRegistryMock();
- SubscriptionControllerMock subController =
- new SubscriptionControllerMock(context, telRegistry, numPhones);
-
- SubscriptionMonitor testedSubMonitor =
- new SubscriptionMonitor(telRegistry, context, subController, numPhones);
-
- TestHandler testHandler = TestHandler.makeHandler();
- Object subChangedObject = new Object();
- testHandler.setSubscriptionChangedObject(subChangedObject);
-
- final int PHONE_ID = 0;
- final int FIRST_SUB_ID = 0;
- final int SECOND_SUB_ID = 1;
-
- testHandler.blockTilIdle();
- Rlog.d(TAG, "1");
-
- testedSubMonitor.registerForSubscriptionChanged(PHONE_ID, testHandler,
- TestHandler.SUBSCRIPTION_CHANGED, subChangedObject);
-
- testHandler.blockTilIdle();
- Rlog.d(TAG, "2");
-
- subController.setSlotSubId(PHONE_ID, FIRST_SUB_ID);
-
- testHandler.blockTilIdle();
- Rlog.d(TAG, "3");
-
- if (testHandler.getSubscriptionChangedCount() != 2) {
- fail("getSubscriptionChangedCount reported " +
- testHandler.getSubscriptionChangedCount() + " != 2");
- }
-
- Rlog.d(TAG, "4");
-
- // cause a notification that subscription info changed
- subController.notifySubscriptionInfoChanged();
- testHandler.blockTilIdle();
-
- Rlog.d(TAG, "5");
-
- if (testHandler.getSubscriptionChangedCount() != 2) {
- fail("getSubscriptionChangedCount reported " +
- testHandler.getSubscriptionChangedCount() + " != 2");
- }
-
- testHandler.die();
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index f2d4a17..08defe3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -32,8 +32,11 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ServiceManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
@@ -50,14 +53,15 @@
import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field;
+import java.util.Map;
@SmallTest
public class TelephonyPermissionsTest {
private static final int SUB_ID = 55555;
private static final int SUB_ID_2 = 22222;
- private static final int PID = 12345;
- private static final int UID = 54321;
+ private static final int PID = Binder.getCallingPid();
+ private static final int UID = Binder.getCallingUid();
private static final String PACKAGE = "com.example";
private static final String MSG = "message";
@@ -70,6 +74,8 @@
@Mock
private ITelephony mMockTelephony;
@Mock
+ private IBinder mMockTelephonyBinder;
+ @Mock
private PackageManager mMockPackageManager;
@Mock
private ApplicationInfo mMockApplicationInfo;
@@ -101,10 +107,13 @@
AppOpsManager.MODE_ERRORED);
when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID)))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+ when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID)))
+ .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED);
when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID),
eq(UID))).thenReturn(false);
+ setTelephonyMockAsService();
}
@Test
@@ -243,8 +252,8 @@
public void testCheckReadDeviceIdentifiers_noPermissions() throws Exception {
setupMocksForDeviceIdentifiersErrorPath();
try {
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG);
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG);
fail("Should have thrown SecurityException");
} catch (SecurityException e) {
// expected
@@ -256,8 +265,8 @@
when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
PID, UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
assertTrue(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -265,8 +274,8 @@
when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), eq(UID)))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
assertTrue(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -274,8 +283,8 @@
when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID,
PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
assertTrue(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -283,8 +292,8 @@
when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), eq(PID),
eq(UID))).thenReturn(true);
assertTrue(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -296,8 +305,8 @@
UID)).thenReturn(PackageManager.PERMISSION_GRANTED);
setupMocksForDeviceIdentifiersErrorPath();
try {
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG);
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG);
fail("Should have thrown SecurityException");
} catch (SecurityException e) {
// expected
@@ -314,8 +323,8 @@
setupMocksForDeviceIdentifiersErrorPath();
mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
assertFalse(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -326,8 +335,8 @@
when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID))).thenReturn(
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
assertTrue(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -340,8 +349,8 @@
when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), eq(UID)))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
assertTrue(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID_2, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -354,8 +363,8 @@
when(mMockAppOps.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, UID,
PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
assertTrue(
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, PACKAGE, MSG));
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
}
@Test
@@ -365,14 +374,79 @@
// case.
setupMocksForDeviceIdentifiersErrorPath();
try {
- TelephonyPermissions.checkReadDeviceIdentifiers(mMockContext, () -> mMockTelephony,
- SUB_ID, PID, UID, null, MSG);
+ TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mMockContext,
+ SUB_ID, null, MSG);
fail("Should have thrown SecurityException");
} catch (SecurityException e) {
// expected
}
}
+ @Test
+ public void testCheckCallingOrSelfReadSubscriberIdentifiers_noPermissions() throws Exception {
+ setupMocksForDeviceIdentifiersErrorPath();
+ setTelephonyMockAsService();
+ when(mMockContext.checkPermission(
+ eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
+ anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
+ when(mMockAppOps.noteOpNoThrow(anyString(), anyInt(), eq(PACKAGE))).thenReturn(
+ AppOpsManager.MODE_ERRORED);
+ when(mMockDevicePolicyManager.checkDeviceIdentifierAccess(eq(PACKAGE), anyInt(),
+ anyInt())).thenReturn(false);
+ try {
+ TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG);
+ fail("Should have thrown SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testCheckCallingOrSelfReadSubscriberIdentifiers_carrierPrivileges()
+ throws Exception {
+ setTelephonyMockAsService();
+ when(mMockContext.checkPermission(
+ eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
+ anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
+ when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID), anyInt()))
+ .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+ assertTrue(
+ TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG));
+ }
+
+ @Test
+ public void testCheckCallingOrSelfReadSubscriberIdentifiers_carrierPrivilegesOnOtherSub()
+ throws Exception {
+ setupMocksForDeviceIdentifiersErrorPath();
+ setTelephonyMockAsService();
+ when(mMockContext.checkPermission(
+ eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
+ anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED);
+ when(mMockSubscriptionManager.getActiveSubscriptionIdList(anyBoolean())).thenReturn(
+ new int[]{SUB_ID, SUB_ID_2});
+ when(mMockTelephony.getCarrierPrivilegeStatusForUid(eq(SUB_ID_2), anyInt())).thenReturn(
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+ // Carrier privilege on the other active sub shouldn't allow access to this sub.
+ try {
+ TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mMockContext,
+ SUB_ID, PACKAGE, MSG);
+ fail("Should have thrown SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ // Put mMockTelephony into service cache so that TELEPHONY_SUPPLIER will get it.
+ private void setTelephonyMockAsService() throws Exception {
+ when(mMockTelephonyBinder.queryLocalInterface(anyString())).thenReturn(mMockTelephony);
+ Field field = ServiceManager.class.getDeclaredField("sCache");
+ field.setAccessible(true);
+ ((Map<String, IBinder>) field.get(null)).put(Context.TELEPHONY_SERVICE,
+ mMockTelephonyBinder);
+ }
+
public static class FakeSettingsConfigProvider extends FakeSettingsProvider {
private static final String PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED =
DeviceConfig.NAMESPACE_PRIVACY + "/"
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 7aa1ff1..3973f6d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -17,7 +17,13 @@
import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
+import static android.telephony.PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED;
import static android.telephony.PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED;
+import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
+import static android.telephony.TelephonyManager.MODEM_COUNT_DUAL_MODEM;
+import static android.telephony.TelephonyManager.RADIO_POWER_OFF;
+import static android.telephony.TelephonyManager.RADIO_POWER_ON;
+import static android.telephony.TelephonyManager.RADIO_POWER_UNAVAILABLE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -25,7 +31,9 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
+import android.content.Intent;
import android.os.ServiceManager;
+import android.telephony.Annotation;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
@@ -51,6 +59,7 @@
private PhoneCapability mPhoneCapability;
private int mActiveSubId;
private int mSrvccState = -1;
+ private int mRadioPowerState = RADIO_POWER_UNAVAILABLE;
public class PhoneStateListenerWrapper extends PhoneStateListener {
@Override
@@ -66,10 +75,15 @@
public void onActiveDataSubscriptionIdChanged(int activeSubId) {
mActiveSubId = activeSubId;
}
+ @Override
+ public void onRadioPowerStateChanged(@Annotation.RadioPowerState int state) {
+ mRadioPowerState = state;
+ }
}
private void addTelephonyRegistryService() {
mServiceManagerMockedServices.put("telephony.registry", mTelephonyRegistry.asBinder());
+ mTelephonyRegistry.systemRunning();
}
@Before
@@ -177,4 +191,35 @@
// pass test!
}
}
+
+ /**
+ * Test multi sim config change.
+ */
+ @Test
+ public void testMultiSimConfigChange() {
+ mTelephonyRegistry.listenForSubscriber(1, mContext.getOpPackageName(),
+ mPhoneStateListener.callback,
+ LISTEN_RADIO_POWER_STATE_CHANGED, true);
+ processAllMessages();
+ assertEquals(RADIO_POWER_UNAVAILABLE, mRadioPowerState);
+
+ // Notify RADIO_POWER_ON on invalid phoneId. Shouldn't go through.
+ mTelephonyRegistry.notifyRadioPowerStateChanged(1, 1, RADIO_POWER_ON);
+ processAllMessages();
+ assertEquals(RADIO_POWER_UNAVAILABLE, mRadioPowerState);
+
+ // Switch to DSDS and re-send RADIO_POWER_ON on phone 1. This time it should be notified.
+ doReturn(MODEM_COUNT_DUAL_MODEM).when(mTelephonyManager).getActiveModemCount();
+ mContext.sendBroadcast(new Intent(ACTION_MULTI_SIM_CONFIG_CHANGED));
+ mTelephonyRegistry.notifyRadioPowerStateChanged(1, 1, RADIO_POWER_ON);
+ processAllMessages();
+ assertEquals(RADIO_POWER_ON, mRadioPowerState);
+
+ // Switch back to single SIM mode and re-send on phone 0. This time it should be notified.
+ doReturn(MODEM_COUNT_DUAL_MODEM).when(mTelephonyManager).getActiveModemCount();
+ mContext.sendBroadcast(new Intent(ACTION_MULTI_SIM_CONFIG_CHANGED));
+ mTelephonyRegistry.notifyRadioPowerStateChanged(0, 1, RADIO_POWER_OFF);
+ processAllMessages();
+ assertEquals(RADIO_POWER_OFF, mRadioPowerState);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 1c05743..6c2faf0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -49,7 +49,6 @@
import android.os.MessageQueue;
import android.os.RegistrantList;
import android.os.ServiceManager;
-import android.os.telephony.TelephonyRegistryManager;
import android.provider.BlockedNumberContract;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -58,6 +57,7 @@
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.euicc.EuiccManager;
import android.telephony.ims.ImsCallProfile;
@@ -620,6 +620,8 @@
replaceInstance(MultiSimSettingController.class, "sInstance", null,
mMultiSimSettingController);
replaceInstance(SubscriptionInfoUpdater.class, "sIsSubInfoInitialized", null, true);
+ replaceInstance(PhoneFactory.class, "sCommandsInterfaces", null,
+ new CommandsInterface[] {mSimulatedCommands});
assertNotNull("Failed to set up SubscriptionController singleton",
SubscriptionController.getInstance());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
index 284a859..9d27abb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
@@ -89,7 +89,7 @@
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mInboundSmsHandler).dispatchIntent(intentArgumentCaptor.capture(),
eq(android.Manifest.permission.RECEIVE_WAP_PUSH),
- eq(AppOpsManager.OP_RECEIVE_WAP_PUSH),
+ eq(AppOpsManager.OPSTR_RECEIVE_WAP_PUSH),
nullable(Bundle.class),
isNull(BroadcastReceiver.class),
eq(UserHandle.SYSTEM),
@@ -143,7 +143,7 @@
verify(mInboundSmsHandler, never()).dispatchIntent(
any(Intent.class),
any(String.class),
- anyInt(),
+ any(String.class),
any(Bundle.class),
any(BroadcastReceiver.class),
any(UserHandle.class),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 101c719..f6ef326 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -720,21 +720,14 @@
any(Message.class));
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
- // Verify the retry manger schedule another data call setup.
- verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
- anyLong(), any(PendingIntent.class));
-
// This time we'll let RIL command succeed.
mSimulatedCommands.setDataCallResult(true, createSetupDataCallResult());
- // Simulate the timer expires.
- Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
- intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
- intent.putExtra("reconnect_alarm_extra_transport_type",
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(intent);
+ //Send event for reconnecting data
+ initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
+ mPhone.getPhoneId(), AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ mApnContext));
waitForMs(200);
dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
@@ -1361,14 +1354,11 @@
verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
anyLong(), any(PendingIntent.class));
- // Simulate the timer expires.
- Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
- intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
- intent.putExtra("reconnect_alarm_extra_transport_type",
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(intent);
+ //Send event for reconnecting data
+ initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
+ mPhone.getPhoneId(), AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ mApnContext));
waitForMs(200);
// Verify if RIL command was sent properly.
@@ -1597,16 +1587,17 @@
eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
+ waitForMs(200);
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.VALID_NETWORK, 0, null));
+ NetworkAgent.VALID_NETWORK, 1, null));
waitForMs(200);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// Verify that its no-op when the new data stall detection feature is disabled
@@ -1638,16 +1629,17 @@
eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
+ waitForMs(200);
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.VALID_NETWORK, 0, null));
+ NetworkAgent.VALID_NETWORK, 1, null));
waitForMs(200);
logd("Sending EVENT_NETWORK_STATUS_CHANGED");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
verify(mSimulatedCommandsVerifier, times(1)).getDataCallList(any(Message.class));
@@ -1680,11 +1672,12 @@
eq(AccessNetworkType.EUTRAN), dpCaptor.capture(),
eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
any(Message.class));
+ waitForMs(200);
verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// expected tear down all DataConnections
@@ -1724,7 +1717,7 @@
logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// expected to get preferred network type
@@ -1761,7 +1754,7 @@
logd("Sending EVENT_NETWORK_STATUS_CHANGED false");
mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_NETWORK_STATUS_CHANGED,
- NetworkAgent.INVALID_NETWORK, 0, null));
+ NetworkAgent.INVALID_NETWORK, 1, null));
waitForMs(200);
// expected to get preferred network type
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
index bb604f4..9250942 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
@@ -16,25 +16,27 @@
package com.android.internal.telephony.dataconnection;
+import static android.net.NetworkFactory.CMD_CANCEL_REQUEST;
+import static android.net.NetworkFactory.CMD_REQUEST_NETWORK;
+
+import static com.android.internal.telephony.dataconnection.TelephonyNetworkFactory.EVENT_ACTIVE_PHONE_SWITCH;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.IConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.StringNetworkSpecifier;
import android.os.AsyncResult;
-import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
-import android.os.Messenger;
import android.telephony.AccessNetworkConstants;
import android.telephony.Rlog;
import android.telephony.data.ApnSetting;
@@ -46,15 +48,9 @@
import com.android.internal.telephony.PhoneSwitcher;
import com.android.internal.telephony.RadioConfig;
-import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.dataconnection.TransportManager.HandoverParams;
import com.android.internal.telephony.dataconnection.TransportManager.HandoverParams.HandoverCallback;
-import com.android.internal.telephony.mocks.ConnectivityServiceMock;
-import com.android.internal.telephony.mocks.PhoneSwitcherMock;
-import com.android.internal.telephony.mocks.SubscriptionControllerMock;
-import com.android.internal.telephony.mocks.SubscriptionMonitorMock;
-import com.android.internal.telephony.mocks.TelephonyRegistryMock;
import org.junit.After;
import org.junit.Before;
@@ -65,26 +61,23 @@
import java.lang.reflect.Field;
import java.util.ArrayList;
+
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class TelephonyNetworkFactoryTest extends TelephonyTest {
private final static String LOG_TAG = "TelephonyNetworkFactoryTest";
@Mock
- private RadioConfig mMockRadioConfig;
+ PhoneSwitcher mPhoneSwitcher;
@Mock
- private IConnectivityManager mIConnectivityManager;
+ private RadioConfig mMockRadioConfig;
private String mTestName = "";
- private TelephonyRegistryMock mTelephonyRegistryMock;
- private PhoneSwitcherMock mPhoneSwitcherMock;
- private SubscriptionControllerMock mSubscriptionControllerMock;
- private SubscriptionMonitorMock mSubscriptionMonitorMock;
- private ConnectivityServiceMock mConnectivityServiceMock;
private final ArrayList<NetworkRequest> mNetworkRequestList = new ArrayList<>();
private TelephonyNetworkFactory mTelephonyNetworkFactoryUT;
+ private int mRequestId = 0;
private void log(String str) {
Rlog.d(LOG_TAG + " " + mTestName, str);
@@ -96,15 +89,51 @@
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED).
addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
netCap.setNetworkSpecifier(new StringNetworkSpecifier(Integer.toString(subId)));
- return mConnectivityServiceMock.requestNetwork(netCap, null, 0, new Binder(), -1);
+ NetworkRequest networkRequest = new NetworkRequest(netCap, -1,
+ mRequestId++, NetworkRequest.Type.REQUEST);
+ mTelephonyNetworkFactoryUT.obtainMessage(CMD_REQUEST_NETWORK, 0, 0, networkRequest)
+ .sendToTarget();
+ return networkRequest;
}
+
+ private NetworkRequest makeDefaultInternetRequest() {
+ NetworkCapabilities netCap = (new NetworkCapabilities())
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ NetworkRequest networkRequest = new NetworkRequest(netCap, -1,
+ mRequestId++, NetworkRequest.Type.REQUEST);
+ mTelephonyNetworkFactoryUT.obtainMessage(CMD_REQUEST_NETWORK, 0, 0, networkRequest)
+ .sendToTarget();
+ return networkRequest;
+ }
+
private NetworkRequest makeSubSpecificMmsRequest(int subId) {
NetworkCapabilities netCap = (new NetworkCapabilities()).
addCapability(NetworkCapabilities.NET_CAPABILITY_MMS).
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED).
addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
netCap.setNetworkSpecifier(new StringNetworkSpecifier(Integer.toString(subId)));
- return mConnectivityServiceMock.requestNetwork(netCap, null, 0, new Binder(), -1);
+ NetworkRequest networkRequest = new NetworkRequest(netCap, -1,
+ mRequestId++, NetworkRequest.Type.REQUEST);
+ mTelephonyNetworkFactoryUT.obtainMessage(CMD_REQUEST_NETWORK, 0, 0, networkRequest)
+ .sendToTarget();
+ return networkRequest;
+ }
+
+ private void releaseNetworkRequest(NetworkRequest networkRequest) {
+ mTelephonyNetworkFactoryUT.obtainMessage(CMD_CANCEL_REQUEST, 0, 0, networkRequest)
+ .sendToTarget();
+ }
+
+ private void activatePhoneInPhoneSwitcher(int phoneId, boolean active) {
+ doReturn(active).when(mPhoneSwitcher).shouldApplyNetworkRequest(any(), eq(phoneId));
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(EVENT_ACTIVE_PHONE_SWITCH);
+ }
+
+ private void activatePhoneInPhoneSwitcher(int phoneId, NetworkRequest nr, boolean active) {
+ doReturn(active).when(mPhoneSwitcher).shouldApplyNetworkRequest(eq(nr), eq(phoneId));
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(EVENT_ACTIVE_PHONE_SWITCH);
}
@Before
@@ -129,47 +158,19 @@
mNetworkRequestList.remove((NetworkRequest) invocation.getArguments()[0]);
return null;
}).when(mDcTracker).releaseNetwork(any(), anyInt());
-
- doAnswer(invocation -> {
- mConnectivityServiceMock.registerNetworkFactory(
- (Messenger) invocation.getArguments()[0],
- (String) invocation.getArguments()[1]);
- return null;
- }).when(mIConnectivityManager).registerNetworkFactory(any(), anyString());
-
- doAnswer(invocation -> {
- mConnectivityServiceMock.unregisterNetworkFactory(
- (Messenger) invocation.getArguments()[0]);
- return null;
- }).when(mIConnectivityManager).unregisterNetworkFactory(any());
}
@After
public void tearDown() throws Exception {
- mConnectivityServiceMock.die();
super.tearDown();
}
- private void createMockedTelephonyComponents(int numberOfPhones) throws Exception {
- mConnectivityServiceMock = new ConnectivityServiceMock(mContext);
- mContextFixture.setSystemService(Context.CONNECTIVITY_SERVICE,
- new ConnectivityManager(mContext, mIConnectivityManager));
- mTelephonyRegistryMock = new TelephonyRegistryMock();
- mSubscriptionControllerMock = new SubscriptionControllerMock(mContext,
- mTelephonyRegistryMock, numberOfPhones);
- mSubscriptionMonitorMock = new SubscriptionMonitorMock(numberOfPhones);
- mPhoneSwitcherMock = new PhoneSwitcherMock(
- numberOfPhones, Looper.myLooper(), mSubscriptionControllerMock);
- mSubscriptionMonitorMock = new SubscriptionMonitorMock(numberOfPhones);
+ private void createMockedTelephonyComponents() throws Exception {
+ replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mPhoneSwitcher);
- replaceInstance(SubscriptionController.class, "sInstance", null,
- mSubscriptionControllerMock);
- replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mPhoneSwitcherMock);
-
- mTelephonyNetworkFactoryUT = new TelephonyNetworkFactory(mSubscriptionMonitorMock,
- Looper.myLooper(), mPhone);
- monitorTestableLooper(new TestableLooper(
- mConnectivityServiceMock.getHandlerThread().getLooper()));
+ mTelephonyNetworkFactoryUT = new TelephonyNetworkFactory(Looper.myLooper(), mPhone);
+ verify(mConnectivityManager).registerNetworkFactory(any(), anyString());
+ verify(mPhoneSwitcher).registerForActivePhoneSwitch(any(), anyInt(), any());
}
/**
@@ -180,24 +181,25 @@
@SmallTest
public void testActive() throws Exception {
mTestName = "testActive";
- final int numberOfPhones = 1;
final int phoneId = 0;
final int subId = 0;
- createMockedTelephonyComponents(numberOfPhones);
+ createMockedTelephonyComponents();
- mPhoneSwitcherMock.setPreferredDataPhoneId(phoneId);
- mSubscriptionControllerMock.setDefaultDataSubId(subId);
- mSubscriptionControllerMock.setSlotSubId(phoneId, subId);
- mSubscriptionMonitorMock.notifySubscriptionChanged(phoneId);
+ doReturn(false).when(mPhoneSwitcher).shouldApplyNetworkRequest(any(), anyInt());
+ doReturn(subId).when(mSubscriptionController).getSubIdUsingPhoneId(phoneId);
+ // fake onSubscriptionChangedListener being triggered.
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
+ TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
log("addDefaultRequest");
- mConnectivityServiceMock.addDefaultRequest();
+ makeDefaultInternetRequest();
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
log("setPhoneActive true: phoneId = " + phoneId);
- mPhoneSwitcherMock.setPhoneActive(phoneId, true);
+
+ activatePhoneInPhoneSwitcher(phoneId, true);
processAllMessages();
assertEquals(1, mNetworkRequestList.size());
@@ -207,7 +209,7 @@
assertEquals(2, mNetworkRequestList.size());
log("setPhoneActive false: phoneId = " + phoneId);
- mPhoneSwitcherMock.setPhoneActive(phoneId, false);
+ activatePhoneInPhoneSwitcher(phoneId, false);
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
@@ -217,27 +219,27 @@
assertEquals(0, mNetworkRequestList.size());
log("setPhoneActive true: phoneId = " + phoneId);
- mPhoneSwitcherMock.setPhoneActive(phoneId, true);
+ activatePhoneInPhoneSwitcher(phoneId, true);
processAllMessages();
assertEquals(3, mNetworkRequestList.size());
log("releaseNetworkRequest: subSpecificDefault = " + subSpecificDefault);
- mConnectivityServiceMock.releaseNetworkRequest(subSpecificDefault);
+ releaseNetworkRequest(subSpecificDefault);
processAllMessages();
assertEquals(2, mNetworkRequestList.size());
log("setPhoneActive false: phoneId = " + phoneId);
- mPhoneSwitcherMock.setPhoneActive(phoneId, false);
+ activatePhoneInPhoneSwitcher(phoneId, false);
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
log("releaseNetworkRequest: subSpecificMms = " + subSpecificMms);
- mConnectivityServiceMock.releaseNetworkRequest(subSpecificMms);
+ releaseNetworkRequest(subSpecificMms);
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
log("setPhoneActive true: phoneId = " + phoneId);
- mPhoneSwitcherMock.setPhoneActive(phoneId, true);
+ activatePhoneInPhoneSwitcher(phoneId, true);
processAllMessages();
assertEquals(1, mNetworkRequestList.size());
}
@@ -256,39 +258,39 @@
final int altSubId = 1;
final int unusedSubId = 2;
- createMockedTelephonyComponents(numberOfPhones);
+ createMockedTelephonyComponents();
- mPhoneSwitcherMock.setPreferredDataPhoneId(phoneId);
- mSubscriptionControllerMock.setDefaultDataSubId(subId);
- mSubscriptionControllerMock.setSlotSubId(phoneId, subId);
- mSubscriptionMonitorMock.notifySubscriptionChanged(phoneId);
+ doReturn(subId).when(mSubscriptionController).getSubIdUsingPhoneId(phoneId);
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
+ TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
- mPhoneSwitcherMock.setPhoneActive(phoneId, true);
+ activatePhoneInPhoneSwitcher(phoneId, true);
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
- mConnectivityServiceMock.addDefaultRequest();
+ makeDefaultInternetRequest();
processAllMessages();
assertEquals(1, mNetworkRequestList.size());
- mSubscriptionControllerMock.setSlotSubId(altPhoneId, altSubId);
+ doReturn(altSubId).when(mSubscriptionController).getSubIdUsingPhoneId(altPhoneId);
processAllMessages();
assertEquals(1, mNetworkRequestList.size());
- mPhoneSwitcherMock.setPreferredDataPhoneId(altPhoneId);
- mSubscriptionControllerMock.setDefaultDataSubId(altSubId);
- mPhoneSwitcherMock.notifyActivePhoneChange(phoneId);
+ activatePhoneInPhoneSwitcher(phoneId, false);
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(EVENT_ACTIVE_PHONE_SWITCH);
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
- makeSubSpecificMmsRequest(subId);
+ NetworkRequest subSpecificMmsRequest = makeSubSpecificMmsRequest(subId);
+ activatePhoneInPhoneSwitcher(phoneId, subSpecificMmsRequest, true);
processAllMessages();
assertEquals(1, mNetworkRequestList.size());
- mSubscriptionControllerMock.setSlotSubId(phoneId, unusedSubId);
- mSubscriptionMonitorMock.notifySubscriptionChanged(phoneId);
+ doReturn(unusedSubId).when(mSubscriptionController).getSubIdUsingPhoneId(phoneId);
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
+ TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
@@ -296,13 +298,12 @@
processAllMessages();
assertEquals(0, mNetworkRequestList.size());
- mSubscriptionControllerMock.setSlotSubId(phoneId, subId);
- mSubscriptionMonitorMock.notifySubscriptionChanged(phoneId);
+ doReturn(subId).when(mSubscriptionController).getSubIdUsingPhoneId(phoneId);
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
+ TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
processAllMessages();
- mSubscriptionControllerMock.setDefaultDataSubId(subId);
- mPhoneSwitcherMock.setPreferredDataPhoneId(phoneId);
- mPhoneSwitcherMock.notifyActivePhoneChange(phoneId);
+ activatePhoneInPhoneSwitcher(phoneId, true);
processAllMessages();
assertEquals(3, mNetworkRequestList.size());
}
@@ -313,14 +314,13 @@
@Test
@SmallTest
public void testHandoverNoLiveData() throws Exception {
- createMockedTelephonyComponents(1);
- mPhoneSwitcherMock.setPreferredDataPhoneId(0);
- mSubscriptionControllerMock.setDefaultDataSubId(0);
- mSubscriptionControllerMock.setSlotSubId(0, 0);
- mSubscriptionMonitorMock.notifySubscriptionChanged(0);
+ createMockedTelephonyComponents();
+ doReturn(0).when(mSubscriptionController).getSubIdUsingPhoneId(0);
+ mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
+ TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
- mPhoneSwitcherMock.setPhoneActive(0, true);
- mConnectivityServiceMock.addDefaultRequest();
+ activatePhoneInPhoneSwitcher(0, true);
+ makeDefaultInternetRequest();
makeSubSpecificMmsRequest(0);
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
index 30baabb..b297ab0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
@@ -925,11 +925,9 @@
}
private void setupResolver(int numSlots) {
- // all tests call setupResolver before running
when(mMockContext.getPackageManager()).thenReturn(mMockPM);
when(mMockContext.getSystemService(eq(Context.CARRIER_CONFIG_SERVICE))).thenReturn(
mMockCarrierConfigManager);
- when(mMockContext.getPackageManager()).thenReturn(mMockPM);
mCarrierConfigs = new PersistableBundle[numSlots];
for (int i = 0; i < numSlots; i++) {
mCarrierConfigs[i] = new PersistableBundle();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index 5914454..5acba72 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -966,6 +966,23 @@
@Test
@SmallTest
+ public void testMergeComplete() {
+ boolean[] result = new boolean[1];
+ // Place a call.
+ ImsPhoneConnection connection = placeCallAndMakeActive();
+ connection.addListener(new Connection.ListenerBase() {
+ @Override
+ public void onConnectionEvent(String event, Bundle extras) {
+ result[0] = android.telecom.Connection.EVENT_MERGE_COMPLETE.equals(event);
+ }
+ });
+ ImsCall call = connection.getImsCall();
+ call.getListener().onCallMerged(call, null, false);
+ assertTrue(result[0]);
+ }
+
+ @Test
+ @SmallTest
public void testNumericOnlyRemap() {
assertEquals(ImsReasonInfo.CODE_SIP_FORBIDDEN, mCTUT.maybeRemapReasonCode(
new ImsReasonInfo(ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE, 0)));
@@ -1005,7 +1022,7 @@
"SERVICE not allowed in this location")));
}
- private void placeCallAndMakeActive() {
+ private ImsPhoneConnection placeCallAndMakeActive() {
try {
doAnswer(new Answer<ImsCall>() {
@Override
@@ -1038,6 +1055,7 @@
new ImsStreamMediaProfile());
imsCall.getImsCallSessionListenerProxy().callSessionStarted(imsCall.getSession(),
new ImsCallProfile());
+ return connection;
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
index 0cdc34c..0db3204 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -35,6 +35,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -63,9 +64,11 @@
import androidx.test.filters.FlakyTest;
+import com.android.ims.FeatureConnector;
import com.android.ims.ImsEcbmStateListener;
import com.android.ims.ImsManager;
import com.android.ims.ImsUtInterface;
+import com.android.ims.RcsFeatureManager;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.CommandsInterface;
@@ -832,6 +835,19 @@
assertNotNull(mImsPhoneUT.getServiceStateTracker());
}
+ @Test
+ @SmallTest
+ public void testRcsFeatureManagerInitialization() throws Exception {
+ FeatureConnector<RcsFeatureManager> mockRcsManagerConnector =
+ (FeatureConnector<RcsFeatureManager>) mock(FeatureConnector.class);
+ mImsPhoneUT.mRcsManagerConnector = mockRcsManagerConnector;
+
+ mImsPhoneUT.initRcsFeatureManager();
+
+ verify(mockRcsManagerConnector).disconnect();
+ assertNotNull(mImsPhoneUT.mRcsManagerConnector);
+ }
+
private ServiceState getServiceStateDataAndVoice(int rat, int regState, boolean isRoaming) {
ServiceState ss = new ServiceState();
ss.setStateOutOfService();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/ConnectivityServiceMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/ConnectivityServiceMock.java
deleted file mode 100644
index 485a8aa..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/ConnectivityServiceMock.java
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Copyright (C) 2008 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.mocks;
-
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
-
-import android.app.PendingIntent;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
-import android.net.NetworkInfo;
-import android.net.NetworkMisc;
-import android.net.NetworkRequest;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
-import com.android.server.connectivity.NetworkAgentInfo;
-
-import java.util.HashMap;
-
-public class ConnectivityServiceMock {
- private static final String TAG = "ConnectivityServiceMock";
- private static final boolean DBG = true;
- private static final boolean VDBG = true;
-
- /**
- * used internally when registering NetworkFactories
- * obj = NetworkFactoryInfo
- */
- private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
-
- /**
- * used internally when registering NetworkAgents
- * obj = Messenger
- */
- private static final int EVENT_REGISTER_NETWORK_AGENT = 18;
-
- /**
- * used to add a network request
- * includes a NetworkRequestInfo
- */
- private static final int EVENT_REGISTER_NETWORK_REQUEST = 19;
-
- /**
- * used to add a network listener - no request
- * includes a NetworkRequestInfo
- */
- private static final int EVENT_REGISTER_NETWORK_LISTENER = 21;
-
- /**
- * used to remove a network request, either a listener or a real request
- * arg1 = UID of caller
- * obj = NetworkRequest
- */
- private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
-
- /**
- * used internally when registering NetworkFactories
- * obj = Messenger
- */
- private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
-
-
- private final HandlerThread mHandlerThread;
- /** Handler used for internal events. */
- final private InternalHandler mHandler;
- /** Handler used for incoming {@link NetworkStateTracker} events. */
- final private NetworkStateTrackerHandler mTrackerHandler;
-
- final private Context mContext;
-
- public ConnectivityServiceMock(Context context) {
- if (DBG) log("starting up");
-
- mContext = context;
- mHandlerThread = new HandlerThread("ConnectivityServiceMock");
- mHandlerThread.start();
- mHandler = new InternalHandler(mHandlerThread.getLooper());
- mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
- }
-
- public void die() {
- // clean up threads/handlers
- if (mHandlerThread != null) {
- mHandlerThread.quit();
- }
- }
-
- public HandlerThread getHandlerThread() {
- return mHandlerThread;
- }
-
- private class InternalHandler extends Handler {
- public InternalHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_REGISTER_NETWORK_FACTORY: {
- handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
- break;
- }
- case EVENT_UNREGISTER_NETWORK_FACTORY: {
- handleUnregisterNetworkFactory((Messenger)msg.obj);
- break;
- }
- case EVENT_REGISTER_NETWORK_AGENT: {
- handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
- break;
- }
- case EVENT_REGISTER_NETWORK_REQUEST:
- case EVENT_REGISTER_NETWORK_LISTENER: {
- handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
- break;
- }
- case EVENT_RELEASE_NETWORK_REQUEST: {
- handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
- break;
- }
- }
- }
- }
-
- private class NetworkStateTrackerHandler extends Handler {
- public NetworkStateTrackerHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- NetworkInfo info;
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
- handleAsyncChannelHalfConnect(msg);
- break;
- }
- case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai != null) nai.asyncChannel.disconnect();
- break;
- }
- case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
- handleAsyncChannelDisconnected(msg);
- break;
- }
- }
- }
- }
-
- private boolean isRequest(NetworkRequest request) {
- return mNetworkRequests.get(request).isRequest;
- }
-
- private void handleAsyncChannelHalfConnect(Message msg) {
- AsyncChannel ac = (AsyncChannel) msg.obj;
- if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- if (VDBG) log("NetworkFactory connected");
- // A network factory has connected. Send it all current NetworkRequests.
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.isRequest == false) continue;
- //NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
- NetworkAgentInfo nai = null;
- ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
- (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
- }
- } else {
- loge("Error connecting NetworkFactory");
- mNetworkFactoryInfos.remove(msg.obj);
- }
- } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- if (VDBG) log("NetworkAgent connected");
- // A network agent has requested a connection. Establish the connection.
- mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
- sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
- } else {
- loge("Error connecting NetworkAgent");
- NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
- //if (nai != null) {
- // final boolean wasDefault = isDefaultNetwork(nai);
- // synchronized (mNetworkForNetId) {
- // mNetworkForNetId.remove(nai.network.netId);
- // mNetIdInUse.delete(nai.network.netId);
- // }
- // // Just in case.
- // mLegacyTypeTracker.remove(nai, wasDefault);
- //}
- }
- }
- }
-
- private void handleAsyncChannelDisconnected(Message msg) {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai != null) {
- if (DBG) {
- log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
- }
- // A network agent has disconnected.
- // TODO - if we move the logic to the network agent (have them disconnect
- // because they lost all their requests or because their score isn't good)
- // then they would disconnect organically, report their new state and then
- // disconnect the channel.
- //if (nai.networkInfo.isConnected()) {
- // nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
- // null, null);
- //}
- //final boolean wasDefault = isDefaultNetwork(nai);
- //if (wasDefault) {
- // mDefaultInetConditionPublished = 0;
- //}
- //notifyIfacesChanged();
- // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
- // by other networks that are already connected. Perhaps that can be done by
- // sending all CALLBACK_LOST messages (for requests, not listens) at the end
- // of rematchAllNetworksAndRequests
- //notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
- //mKeepaliveTracker.handleStopAllKeepalives(nai,
- // ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
- // nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
- mNetworkAgentInfos.remove(msg.replyTo);
- //updateClat(null, nai.linkProperties, nai);
- //synchronized (mNetworkForNetId) {
- // // Remove the NetworkAgent, but don't mark the netId as
- // // available until we've told netd to delete it below.
- // mNetworkForNetId.remove(nai.network.netId);
- //}
- // Remove all previously satisfied requests.
- //for (int i = 0; i < nai.networkRequests.size(); i++) {
- // NetworkRequest request = nai.networkRequests.valueAt(i);
- // NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
- // if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
- // mNetworkForRequestId.remove(request.requestId);
- // sendUpdatedScoreToFactories(request, 0);
- // }
- //}
- //if (nai.networkRequests.get(mDefaultRequest.requestId) != null) {
- // removeDataActivityTracking(nai);
- // notifyLockdownVpn(nai);
- // requestNetworkTransitionWakelock(nai.name());
- //}
- //mLegacyTypeTracker.remove(nai, wasDefault);
- //rematchAllNetworksAndRequests(null, 0);
- //if (nai.created) {
- // // Tell netd to clean up the configuration for this network
- // // (routing rules, DNS, etc).
- // // This may be slow as it requires a lot of netd shelling out to ip and
- // // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
- // // after we've rematched networks with requests which should make a potential
- // // fallback network the default or requested a new network from the
- // // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
- // // long time.
- // try {
- // mNetd.removeNetwork(nai.network.netId);
- // } catch (Exception e) {
- // loge("Exception removing network: " + e);
- // }
- //}
- //synchronized (mNetworkForNetId) {
- // mNetIdInUse.delete(nai.network.netId);
- //}
- } else {
- NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
- if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
- }
- }
-
- private void log(String str) {
- Slog.d(TAG, str);
- }
- private void loge(String str) {
- Slog.e(TAG, str);
- }
-
- // NetworkAgentInfo keyed off its connecting messenger
- // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
- // NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
- private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =
- new HashMap<Messenger, NetworkAgentInfo>();
- private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
- new HashMap<Messenger, NetworkFactoryInfo>();
- private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
- new HashMap<NetworkRequest, NetworkRequestInfo>();
-
- private static class NetworkFactoryInfo {
- public final String name;
- public final Messenger messenger;
- public final AsyncChannel asyncChannel;
- public final int factorySerialNumber;
-
- NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
- int factorySerialNumber) {
- this.name = name;
- this.messenger = messenger;
- this.asyncChannel = asyncChannel;
- this.factorySerialNumber = factorySerialNumber;
- }
- }
-
- private int getCallingUid() {
- return Process.myUid();
- }
-
- private int getCallingPid() {
- return Process.myPid();
- }
-
- private class NetworkRequestInfo implements IBinder.DeathRecipient {
- static final boolean REQUEST = true;
- static final boolean LISTEN = false;
-
- final NetworkRequest request;
- final PendingIntent mPendingIntent;
- boolean mPendingIntentSent;
- private final IBinder mBinder;
- final int mPid;
- final int mUid;
- final Messenger messenger;
- final boolean isRequest;
-
- NetworkRequestInfo(NetworkRequest r, PendingIntent pi, boolean isRequest) {
- request = r;
- mPendingIntent = pi;
- messenger = null;
- mBinder = null;
- mPid = getCallingPid();
- mUid = getCallingUid();
- this.isRequest = isRequest;
- }
-
- NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) {
- super();
- messenger = m;
- request = r;
- mBinder = binder;
- mPid = getCallingPid();
- mUid = getCallingUid();
- this.isRequest = isRequest;
- mPendingIntent = null;
-
- try {
- mBinder.linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- }
- }
-
- void unlinkDeathRecipient() {
- if (mBinder != null) {
- mBinder.unlinkToDeath(this, 0);
- }
- }
-
- public void binderDied() {
- log("ConnectivityService NetworkRequestInfo binderDied(" +
- request + ", " + mBinder + ")");
- releaseNetworkRequest(request);
- }
-
- public String toString() {
- return (isRequest ? "Request" : "Listen") +
- " from uid/pid:" + mUid + "/" + mPid +
- " for " + request +
- (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
- }
- }
-
-
- // sequence number of NetworkRequests
- private int mNextNetworkRequestId = 1;
- private synchronized int nextNetworkRequestId() {
- return mNextNetworkRequestId++;
- }
-
- public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
- Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
- networkCapabilities = new NetworkCapabilities(networkCapabilities);
-
- if (timeoutMs < 0) {
- throw new IllegalArgumentException("Bad timeout specified");
- }
-
- NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
- nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
- NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder, true);
- if (DBG) log("requestNetwork for " + nri);
-
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
-
- return networkRequest;
- }
-
- public void releaseNetworkRequest(NetworkRequest networkRequest) {
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(),
- 0, networkRequest));
- }
-
- public int registerNetworkFactory(Messenger messenger, String name) {
- NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
- NetworkFactory.SerialNumber.nextSerialNumber());
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
- return nfi.factorySerialNumber;
- }
-
- private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
- if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
- mNetworkFactoryInfos.put(nfi.messenger, nfi);
- nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
- }
-
- public void unregisterNetworkFactory(Messenger messenger) {
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
- }
-
- private void handleUnregisterNetworkFactory(Messenger messenger) {
- NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
- if (nfi == null) {
- loge("Failed to find Messenger in unregisterNetworkFactory");
- return;
- }
- if (DBG) log("unregisterNetworkFactory for " + nfi.name);
- }
-
- public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
- LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int currentScore, NetworkMisc networkMisc, int factorySerialNumber) {
-// final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
-// new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
-// linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
-// mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
-// synchronized (this) {
-// nai.networkMonitor.systemReady = mSystemReady;
-// }
-// mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
-// return nai.network.netId;
- throw new RuntimeException("not implemented");
- }
-
- private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
- if (VDBG) log("Got NetworkAgent Messenger");
-// mNetworkAgentInfos.put(na.messenger, na);
-// synchronized (mNetworkForNetId) {
-// mNetworkForNetId.put(na.network.netId, na);
-// }
-// na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
-// NetworkInfo networkInfo = na.networkInfo;
-// na.networkInfo = null;
-// updateNetworkInfo(na, networkInfo);
- }
-
-
- private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
- mNetworkRequests.put(nri.request, nri);
- if (!nri.isRequest) {
- for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
- if (nri.request.networkCapabilities.hasSignalStrength() &&
- network.satisfiesImmutableCapabilitiesOf(nri.request)) {
- }
- }
- }
- rematchAllNetworksAndRequests(null, 0);
- if (nri.isRequest) {
- sendUpdatedScoreToFactories(nri.request, 0);
- }
- }
-
- private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
- NetworkRequestInfo nri = mNetworkRequests.get(request);
- if (nri != null) {
- if (DBG) log("releasing NetworkRequest " + request);
- nri.unlinkDeathRecipient();
- mNetworkRequests.remove(request);
- if (nri.isRequest) {
- // Find all networks that are satisfying this request and remove the request
- // from their request lists.
- // TODO - it's my understanding that for a request there is only a single
- // network satisfying it, so this loop is wasteful
- //boolean wasKept = false;
- //for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- // if (nai.networkRequests.get(nri.request.requestId) != null) {
- // nai.networkRequests.remove(nri.request.requestId);
- // if (DBG) {
- // log(" Removing from current network " + nai.name() +
- // ", leaving " + nai.networkRequests.size() +
- // " requests.");
- // }
- // if (unneeded(nai)) {
- // if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
- // teardownUnneededNetwork(nai);
- // } else {
- // // suspect there should only be one pass through here
- // // but if any were kept do the check below
- // wasKept |= true;
- // }
- // }
- //}
-
- //NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
- //if (nai != null) {
- // mNetworkForRequestId.remove(nri.request.requestId);
- //}
- // Maintain the illusion. When this request arrived, we might have pretended
- // that a network connected to serve it, even though the network was already
- // connected. Now that this request has gone away, we might have to pretend
- // that the network disconnected. LegacyTypeTracker will generate that
- // phantom disconnect for this type.
- //if (nri.request.legacyType != TYPE_NONE && nai != null) {
- // boolean doRemove = true;
- // if (wasKept) {
- // // check if any of the remaining requests for this network are for the
- // // same legacy type - if so, don't remove the nai
- // for (int i = 0; i < nai.networkRequests.size(); i++) {
- // NetworkRequest otherRequest = nai.networkRequests.valueAt(i);
- // if (otherRequest.legacyType == nri.request.legacyType &&
- // isRequest(otherRequest)) {
- // if (DBG) log(" still have other legacy request - leaving");
- // doRemove = false;
- // }
- // }
- // }
- //
- // if (doRemove) {
- // mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
- // }
- //}
-
- for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
- nri.request);
- }
- } else {
- // listens don't have a singular affectedNetwork. Check all networks to see
- // if this listen request applies and remove it.
- //for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- // nai.networkRequests.remove(nri.request.requestId);
- // if (nri.request.networkCapabilities.hasSignalStrength() &&
- // nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
- // updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
- // }
- //}
- }
- //callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED);
- }
- }
-
- private void sendUpdatedScoreToFactories(NetworkAgentInfo nai) {
- for (int i = 0; i < nai.numNetworkRequests(); i++) {
- NetworkRequest nr = nai.requestAt(i);
- // Don't send listening requests to factories. b/17393458
- if (!isRequest(nr)) continue;
- sendUpdatedScoreToFactories(nr, nai.getCurrentScore());
- }
- }
-
- private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
- if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
- for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
- networkRequest);
- }
- }
-
- private void rematchAllNetworksAndRequests(NetworkAgentInfo changed, int oldScore) {
- }
-
- @VisibleForTesting
- public NetworkRequest defaultRequest = null;
- @VisibleForTesting
- public synchronized void addDefaultRequest() {
- if (defaultRequest != null) return;
- NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addCapability(NET_CAPABILITY_INTERNET);
- netCap.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
- defaultRequest = requestNetwork(netCap, null, 0, new Binder(),
- ConnectivityManager.TYPE_NONE);
- }
-
- @VisibleForTesting
- public synchronized void setCurrentScoreForRequest(NetworkRequest nr, int score) {
- sendUpdatedScoreToFactories(nr, score);
- }
-
- @VisibleForTesting
- public synchronized void removeDefaultRequest() {
- if (defaultRequest == null) return;
- releaseNetworkRequest(defaultRequest);
- defaultRequest = null;
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneMock.java
deleted file mode 100644
index 0ce58c2..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneMock.java
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*
- * 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.content.Context;
-import android.net.LinkProperties;
-import android.net.NetworkCapabilities;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Registrant;
-import android.os.RegistrantList;
-import android.os.ResultReceiver;
-import android.os.WorkSource;
-import android.service.carrier.CarrierIdentifier;
-import android.telephony.CellInfo;
-import android.telephony.CellLocation;
-import android.telephony.DataConnectionRealTimeInfo;
-import android.telephony.NetworkScanRequest;
-import android.telephony.ServiceState;
-import android.telephony.SignalStrength;
-import android.telephony.VoLteServiceState;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.test.SimulatedRadioControl;
-import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
-import com.android.internal.telephony.uicc.IccFileHandler;
-import com.android.internal.telephony.uicc.IsimRecords;
-import com.android.internal.telephony.uicc.UiccCard;
-import com.android.internal.telephony.uicc.UsimServiceTable;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * (<em>Not for SDK use</em>)
- * A base implementation for the com.android.internal.telephony.Phone interface.
- *
- * Note that implementations of Phone.java are expected to be used
- * from a single application thread. This should be the same thread that
- * originally called PhoneFactory to obtain the interface.
- *
- * {@hide}
- *
- */
-
-public class PhoneMock extends Phone {
- private static final String LOG_TAG = "PhoneMock";
-
- protected PhoneMock(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
- boolean unitTestMode) {
- super(name, notifier, context, ci, unitTestMode);
- throw new RuntimeException("not implemented");
- }
-
- protected PhoneMock(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
- boolean unitTestMode, int phoneId,
- TelephonyComponentFactory telephonyComponentFactory) {
- super(name, notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory);
- throw new RuntimeException("not implemented");
- }
-
- public String getPhoneName() {
- throw new RuntimeException("not implemented");
- }
-
- protected void setPhoneName(String name) {
- throw new RuntimeException("not implemented");
- }
-
- public String getNai(){
- throw new RuntimeException("not implemented");
- }
-
- public String getActionDetached() {
- return "phonemock.action.detached.not.implemented";
- }
-
- public String getActionAttached() {
- return "phonemock.action.attached.not.implemented";
- }
-
- public void setSystemProperty(String property, String value) {
- throw new RuntimeException("not implemented");
- }
-
- public String getSystemProperty(String property, String defValue) {
- throw new RuntimeException("not implemented");
- }
-
- protected final RegistrantList mPreciseCallStateRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mHandoverRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mRedialRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mNewRingingConnectionRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mIncomingRingRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mDisconnectRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mServiceStateRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mMmiCompleteRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mMmiRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mUnknownConnectionRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mSuppServiceFailedRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mRadioOffOrNotAvailableRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mSimRecordsLoadedRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mVideoCapabilityChangedRegistrants
- = new RegistrantList();
-
- protected final RegistrantList mEmergencyCallToggledRegistrants
- = new RegistrantList();
-
-
- public void startMonitoringImsService() {
- throw new RuntimeException("not implemented");
- }
-
- @Override
- public void handleMessage(Message msg) {
- throw new RuntimeException("not implemented");
- }
-
- @Override
- public boolean handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback) {
- throw new RuntimeException("not implemented");
- }
-
- public ArrayList<Connection> getHandoverConnection() {
- throw new RuntimeException("not implemented");
- }
-
- public void notifySrvccState(Call.SrvccState state) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForSilentRedial(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForSilentRedial(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public Context getContext() {
- return mContext;
- }
-
- protected void onUpdateIccAvailability() {
- throw new RuntimeException("not implemented");
- }
-
- public void disableDnsCheck(boolean b) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isDnsCheckDisabled() {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
- mPreciseCallStateRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForPreciseCallStateChanged(Handler h) {
- mPreciseCallStateRegistrants.remove(h);
- }
-
- protected void notifyPreciseCallStateChangedP() {
- AsyncResult ar = new AsyncResult(null, this, null);
- mPreciseCallStateRegistrants.notifyRegistrants(ar);
-
- mNotifier.notifyPreciseCallState(this);
- }
-
- public void registerForHandoverStateChanged(Handler h, int what, Object obj) {
- mHandoverRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForHandoverStateChanged(Handler h) {
- mHandoverRegistrants.remove(h);
- }
-
- public void notifyHandoverStateChanged(Connection cn) {
- AsyncResult ar = new AsyncResult(null, cn, null);
- mHandoverRegistrants.notifyRegistrants(ar);
- }
-
- public void registerForRedialConnectionChanged(Handler h, int what, Object obj) {
- mRedialRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForRedialConnectionChanged(Handler h) {
- mRedialRegistrants.remove(h);
- }
-
- public void notifyRedialConnectionChanged(Connection cn) {
- AsyncResult ar = new AsyncResult(null, cn, null);
- mRedialRegistrants.notifyRegistrants(ar);
- }
-
- public void migrateFrom(Phone from) {
- throw new RuntimeException("not implemented");
- }
-
- public void migrate(RegistrantList to, RegistrantList from) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForUnknownConnection(Handler h, int what, Object obj) {
- mUnknownConnectionRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForUnknownConnection(Handler h) {
- mUnknownConnectionRegistrants.remove(h);
- }
-
- public void registerForNewRingingConnection(
- Handler h, int what, Object obj) {
- mNewRingingConnectionRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForNewRingingConnection(Handler h) {
- mNewRingingConnectionRegistrants.remove(h);
- }
-
- public void registerForVideoCapabilityChanged(
- Handler h, int what, Object obj) {
- mVideoCapabilityChangedRegistrants.addUnique(h, what, obj);
- notifyForVideoCapabilityChanged(mIsVideoCapable);
- }
-
- public void unregisterForVideoCapabilityChanged(Handler h) {
- mVideoCapabilityChangedRegistrants.remove(h);
- }
-
- public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForInCallVoicePrivacyOn(Handler h){
- throw new RuntimeException("not implemented");
- }
-
- public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForInCallVoicePrivacyOff(Handler h){
- throw new RuntimeException("not implemented");
- }
-
- public void registerForIncomingRing(
- Handler h, int what, Object obj) {
- mIncomingRingRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForIncomingRing(Handler h) {
- mIncomingRingRegistrants.remove(h);
- }
-
- public void registerForDisconnect(Handler h, int what, Object obj) {
- mDisconnectRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForDisconnect(Handler h) {
- mDisconnectRegistrants.remove(h);
- }
-
- public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
- mSuppServiceFailedRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForSuppServiceFailed(Handler h) {
- mSuppServiceFailedRegistrants.remove(h);
- }
-
- public void registerForMmiInitiate(Handler h, int what, Object obj) {
- mMmiRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForMmiInitiate(Handler h) {
- mMmiRegistrants.remove(h);
- }
-
- public void registerForMmiComplete(Handler h, int what, Object obj) {
- mMmiCompleteRegistrants.addUnique(h, what, obj);
- }
-
- public void unregisterForMmiComplete(Handler h) {
- mMmiCompleteRegistrants.remove(h);
- }
-
- public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForSimRecordsLoaded(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForTtyModeReceived(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForTtyModeReceived(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void setNetworkSelectionModeAutomatic(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void getNetworkSelectionMode(Message message) {
- throw new RuntimeException("not implemented");
- }
-
- public void selectNetworkManually(OperatorInfo network, boolean persistSelection,
- Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForEmergencyCallToggle(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- mEmergencyCallToggledRegistrants.add(r);
- }
-
- public void unregisterForEmergencyCallToggle(Handler h) {
- mEmergencyCallToggledRegistrants.remove(h);
- }
-
- public void restoreSavedNetworkSelection(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void saveClirSetting(int commandInterfaceCLIRMode) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForServiceStateChanged(Handler h, int what, Object obj) {
- mServiceStateRegistrants.add(h, what, obj);
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForServiceStateChanged(Handler h) {
- mServiceStateRegistrants.remove(h);
- throw new RuntimeException("not implemented");
- }
-
- public void registerForRingbackTone(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForRingbackTone(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForOnHoldTone(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForOnHoldTone(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForResendIncallMute(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForResendIncallMute(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void setEchoSuppressionEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public SimulatedRadioControl getSimulatedRadioControl() {
- throw new RuntimeException("not implemented");
- }
-
- public PhoneConstants.State getState() {
- throw new RuntimeException("not implemented");
- }
-
- public IccFileHandler getIccFileHandler(){
- throw new RuntimeException("not implemented");
- }
-
- public Handler getHandler() {
- return this;
- }
-
- public void updatePhoneObject(int voiceRadioTech) {
- throw new RuntimeException("not implemented");
- }
-
- public ServiceStateTracker getServiceStateTracker() {
- throw new RuntimeException("not implemented");
- }
-
- public CallTracker getCallTracker() {
- throw new RuntimeException("not implemented");
- }
-
- public AppType getCurrentUiccAppType() {
- throw new RuntimeException("not implemented");
- }
-
- public IccCard getIccCard() {
- throw new RuntimeException("not implemented");
- }
-
- public String getIccSerialNumber() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean getIccRecordsLoaded() {
- throw new RuntimeException("not implemented");
- }
-
- public List<CellInfo> getAllCellInfo() {
- throw new RuntimeException("not implemented");
- }
-
- public void setCellInfoListRate(int rateInMillis) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean getMessageWaitingIndicator() {
- throw new RuntimeException("not implemented");
- }
-
- public void setVoiceCallForwardingFlag(int line, boolean enable, String number) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean getCallForwardingIndicator() {
- throw new RuntimeException("not implemented");
- }
-
- public void queryCdmaRoamingPreference(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public SignalStrength getSignalStrength() {
- throw new RuntimeException("not implemented");
- }
-
- public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void setPreferredNetworkType(int networkType, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void getPreferredNetworkType(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void getSmscAddress(Message result) {
- throw new RuntimeException("not implemented");
- }
-
- public void setSmscAddress(String address, Message result) {
- throw new RuntimeException("not implemented");
- }
-
- public void setTTYMode(int ttyMode, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void setUiTTYMode(int uiTtyMode, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void queryTTYMode(Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void getEnhancedVoicePrivacy(Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void setBandMode(int bandMode, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void queryAvailableBandMode(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void invokeOemRilRequestRaw(byte[] data, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void invokeOemRilRequestStrings(String[] strings, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void nvReadItem(int itemID, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void nvWriteItem(int itemID, String itemValue, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void nvResetConfig(int resetType, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyDataActivity() {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyMessageWaitingIndicator() {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyDataConnection(String reason, String apnType,
- PhoneConstants.DataState state) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyDataConnection(String reason, String apnType) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyDataConnection(String reason) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyOtaspChanged(int otaspMode) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifySignalStrength() {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyCellInfo(List<CellInfo> cellInfo) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
- throw new RuntimeException("not implemented");
- }
-
- private final AtomicBoolean mInEmergencyCall = new AtomicBoolean(false);
-
- public boolean isInEmergencyCall() {
- return mInEmergencyCall.get();
- }
-
- @VisibleForTesting
- public void setInEmergencyCall(boolean value) {
- final boolean oldValue = mInEmergencyCall.getAndSet(value);
- if (oldValue != value) {
- mEmergencyCallToggledRegistrants.notifyRegistrants();
- }
- }
-
- private final AtomicBoolean mInEcm = new AtomicBoolean(false);
-
- public boolean isInEcm() {
- return mInEcm.get();
- }
-
- @VisibleForTesting
- public void setInEcm(boolean value) {
- final boolean oldValue = mInEcm.getAndSet(value);
- if (oldValue != value) {
- mEmergencyCallToggledRegistrants.notifyRegistrants();
- }
- }
-
- public boolean isVideoCallPresent() {
- throw new RuntimeException("not implemented");
- }
-
- public int getPhoneType() {
- return PhoneConstants.PHONE_TYPE_GSM;
- }
-
- public int getPrecisePhoneType() {
- throw new RuntimeException("not implemented");
- }
-
- public int getVoiceMessageCount(){
- throw new RuntimeException("not implemented");
- }
-
- public void setVoiceMessageCount(int countWaiting) {
- throw new RuntimeException("not implemented");
- }
-
- public int getCdmaEriIconIndex() {
- throw new RuntimeException("not implemented");
- }
-
- public int getCdmaEriIconMode() {
- throw new RuntimeException("not implemented");
- }
-
- public String getCdmaEriText() {
- throw new RuntimeException("not implemented");
- }
-
- public String getCdmaMin() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isMinInfoReady() {
- throw new RuntimeException("not implemented");
- }
-
- public String getCdmaPrlVersion(){
- throw new RuntimeException("not implemented");
- }
-
- public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void exitEmergencyCallbackMode() {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForCdmaOtaStatusChange(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForSubscriptionInfoReady(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean needsOtaServiceProvisioning() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isOtaSpNumber(String dialStr) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForCallWaiting(Handler h, int what, Object obj){
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForCallWaiting(Handler h){
- throw new RuntimeException("not implemented");
- }
-
- public void registerForEcmTimerReset(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForEcmTimerReset(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForSignalInfo(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForSignalInfo(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForDisplayInfo(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForDisplayInfo(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForNumberInfo(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForNumberInfo(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForRedirectedNumberInfo(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForLineControlInfo(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForLineControlInfo(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForT53ClirInfo(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForT53AudioControlInfo(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
- throw new RuntimeException("not implemented");
- }
-
- public void unsetOnEcbModeExitResponse(Handler h){
- throw new RuntimeException("not implemented");
- }
-
- public void registerForRadioOffOrNotAvailable(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForRadioOffOrNotAvailable(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public String[] getActiveApnTypes() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean hasMatchedTetherApnSetting() {
- throw new RuntimeException("not implemented");
- }
-
- public String getActiveApnHost(String apnType) {
- throw new RuntimeException("not implemented");
- }
-
- public LinkProperties getLinkProperties(String apnType) {
- throw new RuntimeException("not implemented");
- }
-
- public NetworkCapabilities getNetworkCapabilities(String apnType) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isDataAllowed() {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyNewRingingConnectionP(Connection cn) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyUnknownConnectionP(Connection cn) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyForVideoCapabilityChanged(boolean isVideoCallCapable) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isCspPlmnEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public IsimRecords getIsimRecords() {
- throw new RuntimeException("not implemented");
- }
-
- public String getMsisdn() {
- throw new RuntimeException("not implemented");
- }
-
- public PhoneConstants.DataState getDataConnectionState() {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyCallForwardingIndicator() {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyDataConnectionFailed(String reason, String apnType) {
- throw new RuntimeException("not implemented");
- }
-
- public void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
- String failCause) {
- throw new RuntimeException("not implemented");
- }
-
- public int getLteOnCdmaMode() {
- throw new RuntimeException("not implemented");
- }
-
- public void setVoiceMessageWaiting(int line, int countWaiting) {
- throw new RuntimeException("not implemented");
- }
-
- public UsimServiceTable getUsimServiceTable() {
- throw new RuntimeException("not implemented");
- }
-
- public UiccCard getUiccCard() {
- throw new RuntimeException("not implemented");
- }
-
- public String[] getPcscfAddress(String apnType) {
- throw new RuntimeException("not implemented");
- }
-
- public void setImsRegistrationState(boolean registered) {
- throw new RuntimeException("not implemented");
- }
-
- public Phone getImsPhone() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isUtEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public void dispose() {
- throw new RuntimeException("not implemented");
- }
-
- public int getSubId() {
- throw new RuntimeException("not implemented");
- }
-
- public int getPhoneId() {
- throw new RuntimeException("not implemented");
- }
-
- public int getVoicePhoneServiceState() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean setOperatorBrandOverride(String brand) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean setRoamingOverride(List<String> gsmRoamingList,
- List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
- List<String> cdmaNonRoamingList) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isMccMncMarkedAsRoaming(String mccMnc) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isMccMncMarkedAsNonRoaming(String mccMnc) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isSidMarkedAsRoaming(int SID) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isSidMarkedAsNonRoaming(int SID) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isImsRegistered() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isWifiCallingEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isVolteEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isRadioAvailable() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isRadioOn() {
- throw new RuntimeException("not implemented");
- }
-
- public void shutdownRadio() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isShuttingDown() {
- throw new RuntimeException("not implemented");
- }
-
- public void setRadioCapability(RadioCapability rc, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public int getRadioAccessFamily() {
- throw new RuntimeException("not implemented");
- }
-
- public String getModemUuId() {
- throw new RuntimeException("not implemented");
- }
-
- public RadioCapability getRadioCapability() {
- throw new RuntimeException("not implemented");
- }
-
- public void radioCapabilityUpdated(RadioCapability rc) {
- throw new RuntimeException("not implemented");
- }
-
- public void sendSubscriptionSettings(boolean restoreNetworkSelection) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForRadioCapabilityChanged(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForRadioCapabilityChanged(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isImsUseEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isVideoEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public int getLceStatus() {
- throw new RuntimeException("not implemented");
- }
-
- public void getModemActivityInfo(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void setAllowedCarriers(List<CarrierIdentifier> carrierList, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void getAllowedCarriers(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void startLceAfterRadioIsAvailable() {
- throw new RuntimeException("not implemented");
- }
-
- public Locale getLocaleFromSimAndCarrierPrefs() {
- throw new RuntimeException("not implemented");
- }
-
- public void updateDataConnectionTracker() {
- throw new RuntimeException("not implemented");
- }
-
- public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean updateCurrentCarrierInProvider() {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForAllDataDisconnected(Handler h, int what) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForAllDataDisconnected(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public IccSmsInterfaceManager getIccSmsInterfaceManager(){
- throw new RuntimeException("not implemented");
- }
-
- public static void checkWfcWifiOnlyModeBeforeDial(Phone imsPhone, Context context) {
- throw new RuntimeException("not implemented");
- }
-
- public void startRingbackTone() {
- throw new RuntimeException("not implemented");
- }
-
- public void stopRingbackTone() {
- throw new RuntimeException("not implemented");
- }
-
- public void callEndCleanupHandOverCallIfAny() {
- throw new RuntimeException("not implemented");
- }
-
- public void cancelUSSD(Message msg) {
- throw new RuntimeException("not implemented");
- }
-
- public void setBroadcastEmergencyCallStateChanges(boolean broadcast) {
- throw new RuntimeException("not implemented");
- }
-
- public void sendEmergencyCallStateChange(boolean callActive) {
- throw new RuntimeException("not implemented");
- }
-
- public Phone getDefaultPhone() {
- throw new RuntimeException("not implemented");
- }
-
- /** From PhoneInternalInterface - man this class has alot of functions */
- public ServiceState getServiceState() {
- throw new RuntimeException("not implemented");
- }
-
- public CellLocation getCellLocation(WorkSource workSource) {
- throw new RuntimeException("not implemented");
- }
-
- public DataActivityState getDataActivityState() {
- throw new RuntimeException("not implemented");
- }
-
- public List<? extends MmiCode> getPendingMmiCodes() {
- throw new RuntimeException("not implemented");
- }
-
- public void sendUssdResponse(String ussdMessge) {
- throw new RuntimeException("not implemented");
- }
-
- public void registerForSuppServiceNotification(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void unregisterForSuppServiceNotification(Handler h) {
- throw new RuntimeException("not implemented");
- }
-
- public void acceptCall(int videoState) throws CallStateException {
- throw new RuntimeException("not implemented");
- }
-
- public void rejectCall() throws CallStateException {
- throw new RuntimeException("not implemented");
- }
-
- public void switchHoldingAndActive() throws CallStateException {
- throw new RuntimeException("not implemented");
- }
-
- public boolean canConference() {
- throw new RuntimeException("not implemented");
- }
-
- public void conference() throws CallStateException {
- throw new RuntimeException("not implemented");
- }
-
- public boolean canTransfer() {
- throw new RuntimeException("not implemented");
- }
-
- public void explicitCallTransfer() throws CallStateException {
- throw new RuntimeException("not implemented");
- }
-
- public void clearDisconnected() {
- throw new RuntimeException("not implemented");
- }
-
- public Call getForegroundCall() {
- throw new RuntimeException("not implemented");
- }
-
- public Call getBackgroundCall() {
- throw new RuntimeException("not implemented");
- }
-
- public Call getRingingCall() {
- throw new RuntimeException("not implemented");
- }
-
- @Override
- public Connection dial(String dialString, DialArgs dialArgs) throws CallStateException {
- throw new RuntimeException("not implemented");
- }
-
- public boolean handlePinMmi(String dialString) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean handleUssdServiceCall(String dialString, Callback wrappedCallback) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean handleInCallMmiCommands(String command) throws CallStateException {
- throw new RuntimeException("not implemented");
- }
-
- public void sendDtmf(char c) {
- throw new RuntimeException("not implemented");
- }
-
- public void startDtmf(char c) {
- throw new RuntimeException("not implemented");
- }
-
- public void stopDtmf() {
- throw new RuntimeException("not implemented");
- }
-
- public void setRadioPower(boolean power) {
- throw new RuntimeException("not implemented");
- }
-
- public String getLine1Number() {
- throw new RuntimeException("not implemented");
- }
-
- public String getLine1AlphaTag() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean setLine1Number(String alphaTag, String number, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public String getVoiceMailNumber() {
- throw new RuntimeException("not implemented");
- }
-
- public String getVoiceMailAlphaTag() {
- throw new RuntimeException("not implemented");
- }
-
- public void setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void setCallForwardingOption(int commandInterfaceCFReason, int commandInterfaceCFAction,
- String dialingNumber, int timerSeconds, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void getCallBarring(String facility, String password, Message onComplete,
- int serviceClass) {
- }
-
- public void setCallBarring(String facility, boolean lockState, String password,
- Message onComplete, int serviceClass) {
- }
-
- public void getOutgoingCallerIdDisplay(Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void getCallWaiting(Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void setCallWaiting(boolean enable, Message onComplete) {
- throw new RuntimeException("not implemented");
- }
-
- public void getAvailableNetworks(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void startNetworkScan(NetworkScanRequest nsr, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void stopNetworkScan(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void setOnPostDialCharacter(Handler h, int what, Object obj) {
- throw new RuntimeException("not implemented");
- }
-
- public void setMute(boolean muted) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean getMute() {
- throw new RuntimeException("not implemented");
- }
-
- public void getDataCallList(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void updateServiceLocation() {
- throw new RuntimeException("not implemented");
- }
-
- public void enableLocationUpdates() {
- throw new RuntimeException("not implemented");
- }
-
- public void disableLocationUpdates() {
- throw new RuntimeException("not implemented");
- }
-
- public boolean getDataRoamingEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public void setDataRoamingEnabled(boolean enable) {
- throw new RuntimeException("not implemented");
- }
-
- public boolean isUserDataEnabled() {
- throw new RuntimeException("not implemented");
- }
-
- public String getDeviceId() {
- throw new RuntimeException("not implemented");
- }
-
- public String getDeviceSvn() {
- throw new RuntimeException("not implemented");
- }
-
- public String getSubscriberId() {
- throw new RuntimeException("not implemented");
- }
-
- public String getGroupIdLevel1() {
- throw new RuntimeException("not implemented");
- }
-
- public String getGroupIdLevel2() {
- throw new RuntimeException("not implemented");
- }
-
- public String getEsn() {
- throw new RuntimeException("not implemented");
- }
-
- public String getMeid() {
- throw new RuntimeException("not implemented");
- }
-
- public String getImei() {
- throw new RuntimeException("not implemented");
- }
-
- public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() {
- throw new RuntimeException("not implemented");
- }
-
- public void activateCellBroadcastSms(int activate, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void getCellBroadcastSmsConfig(Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
- throw new RuntimeException("not implemented");
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- throw new RuntimeException("not implemented");
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneSwitcherMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneSwitcherMock.java
deleted file mode 100644
index b53a28f..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/PhoneSwitcherMock.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.mocks;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Registrant;
-import android.os.RegistrantList;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.PhoneSwitcher;
-import com.android.internal.telephony.SubscriptionController;
-
-import java.lang.reflect.Field;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class PhoneSwitcherMock extends PhoneSwitcher {
- private final RegistrantList mActivePhoneRegistrants;
- private final AtomicBoolean mIsActive[];
-
- public PhoneSwitcherMock(int numPhones, Looper looper, SubscriptionController subController)
- throws Exception {
- super(numPhones, looper);
-
- mActivePhoneRegistrants = new RegistrantList();
- mIsActive = new AtomicBoolean[numPhones];
- for(int i = 0; i < numPhones; i++) {
- mIsActive[i] = new AtomicBoolean(false);
- }
-
- if (subController != null) {
- Field subControllerField =
- this.getClass().getSuperclass().getDeclaredField("mSubscriptionController");
- subControllerField.setAccessible(true);
- subControllerField.set(this, subController);
- }
- }
-
- @Override
- public void onRadioCapChanged(int phoneId) {
- throw new RuntimeException("resendPhone not implemented");
- }
-
- @Override
- protected boolean isPhoneActive(int phoneId) {
- return mIsActive[phoneId].get();
- }
-
- @Override
- public void registerForActivePhoneSwitch(Handler h, int what, Object o) {
- Registrant r = new Registrant(h, what, o);
- mActivePhoneRegistrants.add(r);
- r.notifyRegistrant();
- }
-
- @Override
- public void unregisterForActivePhoneSwitch(Handler h) {
- mActivePhoneRegistrants.remove(h);
- }
-
- @VisibleForTesting
- public void setPhoneActive(int phoneId, boolean active) {
- validatePhoneId(phoneId);
- if (mIsActive[phoneId].getAndSet(active) != active) {
- notifyActivePhoneChange(phoneId);
- }
- }
-
- public void setPreferredDataPhoneId(int preferredDataPhoneId) {
- mPreferredDataPhoneId = preferredDataPhoneId;
- }
-
- public void notifyActivePhoneChange(int phoneId) {
- mActivePhoneRegistrants.notifyRegistrants();
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionControllerMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionControllerMock.java
deleted file mode 100644
index 03ef19d..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionControllerMock.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.mocks;
-
-import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
-import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.telephony.SubscriptionInfo;
-
-import com.android.internal.telephony.ITelephonyRegistry;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.SubscriptionController;
-import com.android.internal.telephony.TelephonyIntents;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-// must extend SubscriptionController as some people use it directly within-process
-public class SubscriptionControllerMock extends SubscriptionController {
- final AtomicInteger mDefaultDataSubId = new AtomicInteger(INVALID_SUBSCRIPTION_ID);
- final AtomicInteger mDefaultVoiceSubId = new AtomicInteger(INVALID_SUBSCRIPTION_ID);
- final ITelephonyRegistry.Stub mTelephonyRegistry;
- final int[][] mSlotIndexToSubId;
-
- public static SubscriptionController init(Context c) {
- throw new RuntimeException("not implemented");
- }
- public static SubscriptionController getInstance() {
- throw new RuntimeException("not implemented");
- }
-
- public SubscriptionControllerMock(Context c, ITelephonyRegistry.Stub tr, int phoneCount) {
- super(c);
- mTelephonyRegistry = tr;
- mSlotIndexToSubId = new int[phoneCount][];
- for (int i = 0; i < phoneCount; i++) {
- mSlotIndexToSubId[i] = new int[1];
- mSlotIndexToSubId[i][0] = INVALID_SUBSCRIPTION_ID;
- }
- }
-
- protected void internalInit(Context c) {
- mContext = c;
- }
-
- @Override
- public int getDefaultDataSubId() {
- return mDefaultDataSubId.get();
- }
-
- @Override
- public void setDefaultDataSubId(int subId) {
- if (subId == DEFAULT_SUBSCRIPTION_ID) {
- throw new RuntimeException("setDefaultDataSubId called with DEFAULT_SUB_ID");
- }
-
- mDefaultDataSubId.set(subId);
- broadcastDefaultDataSubIdChanged(subId);
- }
-
- private void broadcastDefaultDataSubIdChanged(int subId) {
- // Broadcast an Intent for default data sub change
- Intent intent = new Intent(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
- mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
- }
-
- @Override
- public int getSubIdUsingPhoneId(int phoneId) {
- int[] subIds = getSubId(phoneId);
- if (subIds == null || subIds.length == 0) {
- return INVALID_SUBSCRIPTION_ID;
- }
- return subIds[0];
- }
-
- @Override
- public void notifySubscriptionInfoChanged() {
- try {
- mTelephonyRegistry.notifySubscriptionInfoChanged();
- } catch (RemoteException ex) {}
- }
- @Override
- public SubscriptionInfo getActiveSubscriptionInfo(int subId, String callingPackage) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String cp){
- throw new RuntimeException("not implemented");
- }
- @Override
- public List<SubscriptionInfo> getAllSubInfoList(String callingPackage) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public List<SubscriptionInfo> getActiveSubscriptionInfoList(String callingPackage) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int getActiveSubInfoCount(String callingPackage) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int getAllSubInfoCount(String callingPackage) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int getActiveSubInfoCountMax() {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int addSubInfoRecord(String iccId, int slotIndex) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int addSubInfo(String uniqueId, String displayName, int slotIndex,
- int subscriptionType) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int removeSubInfo(String uniqueId, int subscriptionType) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public boolean setPlmnSpn(int slotIndex, boolean showPlmn, String plmn, boolean showSpn,
- String spn) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int setIconTint(int tint, int subId) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int setDisplayNameUsingSrc(String displayName, int subId, int nameSource) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int setDisplayNumber(String number, int subId) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int setDataRoaming(int roaming, int subId) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int setMccMnc(String mccMnc, int subId) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int getSlotIndex(int subId) {
- throw new RuntimeException("not implemented");
- }
-
- private boolean isInvalidslotIndex(int slotIndex) {
- if (slotIndex < 0 || slotIndex >= mSlotIndexToSubId.length) return true;
- return false;
- }
-
- @Override
- public int[] getSubId(int slotIndex) {
- if (isInvalidslotIndex(slotIndex)) {
- return null;
- }
- return mSlotIndexToSubId[slotIndex];
- }
- public void setSlotSubId(int slotIndex, int subId) {
- if (isInvalidslotIndex(slotIndex)) {
- throw new RuntimeException("invalid slot specified" + slotIndex);
- }
- if (mSlotIndexToSubId[slotIndex][0] != subId) {
- mSlotIndexToSubId[slotIndex][0] = subId;
- try {
- mTelephonyRegistry.notifySubscriptionInfoChanged();
- } catch (RemoteException ex) {}
- }
- }
- @Override
- public int getPhoneId(int subId) {
- if (subId <= INVALID_SUBSCRIPTION_ID) return INVALID_PHONE_INDEX;
-
- for (int i = 0; i < mSlotIndexToSubId.length; i++) {
- if (mSlotIndexToSubId[i][0] == subId) return i;
- }
- return INVALID_PHONE_INDEX;
- }
- @Override
- public int clearSubInfo() {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int getDefaultSubId() {
- throw new RuntimeException("not implemented");
- }
- @Override
- public void setDefaultSmsSubId(int subId) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int getDefaultSmsSubId() {
- throw new RuntimeException("not implemented");
- }
- @Override
- public void setDefaultVoiceSubId(int subId) {
- if (subId == DEFAULT_SUBSCRIPTION_ID) {
- throw new RuntimeException("setDefaultDataSubId called with DEFAULT_SUB_ID");
- }
- mDefaultVoiceSubId.set(subId);
- broadcastDefaultVoiceSubIdChanged(subId);
- }
- @Override
- public int getDefaultVoiceSubId() {
- if (mDefaultVoiceSubId != null) {
- return mDefaultVoiceSubId.get();
- } else {
- return INVALID_SUBSCRIPTION_ID;
- }
- }
- @Override
- public void updatePhonesAvailability(Phone[] phones) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int[] getActiveSubIdList(boolean visibleOnly) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public boolean isActiveSubId(int subId) {
- return getPhoneId(subId) != INVALID_PHONE_INDEX;
- }
- @Override
- public int getSimStateForSlotIndex(int slotIndex) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public int setSubscriptionProperty(int subId, String propKey, String propValue) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public String getSubscriptionProperty(int subId, String propKey, String callingPackage) {
- throw new RuntimeException("not implemented");
- }
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- throw new RuntimeException("not implemented");
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionMonitorMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionMonitorMock.java
deleted file mode 100644
index 7579359..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionMonitorMock.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.mocks;
-
-import android.os.Handler;
-import android.os.Registrant;
-import android.os.RegistrantList;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.SubscriptionMonitor;
-
-public class SubscriptionMonitorMock extends SubscriptionMonitor {
- private final int mNumPhones;
- private final RegistrantList mSubscriptionsChangedRegistrants[];
-
- public SubscriptionMonitorMock(int numPhones) {
- super();
- mNumPhones = numPhones;
- mSubscriptionsChangedRegistrants = new RegistrantList[numPhones];
-
- for (int i = 0; i < numPhones; i++) {
- mSubscriptionsChangedRegistrants[i] = new RegistrantList();
- }
- }
-
- @Override
- public void registerForSubscriptionChanged(int phoneId, Handler h, int what, Object o) {
- validatePhoneId(phoneId);
- Registrant r = new Registrant(h, what, o);
- mSubscriptionsChangedRegistrants[phoneId].add(r);
- r.notifyRegistrant();
- }
-
- @Override
- public void unregisterForSubscriptionChanged(int phoneId, Handler h) {
- validatePhoneId(phoneId);
- mSubscriptionsChangedRegistrants[phoneId].remove(h);
- }
-
- @VisibleForTesting
- public void notifySubscriptionChanged(int phoneId) {
- validatePhoneId(phoneId);
- mSubscriptionsChangedRegistrants[phoneId].notifyRegistrants();
- }
-
- private void validatePhoneId(int phoneId) {
- if (phoneId < 0 || phoneId >= mNumPhones) {
- throw new IllegalArgumentException("Invalid PhoneId");
- }
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
deleted file mode 100644
index bc2cf62..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.mocks;
-
-import android.net.LinkProperties;
-import android.net.NetworkCapabilities;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.telephony.Annotation.DataFailureCause;
-import android.telephony.CallQuality;
-import android.telephony.CellInfo;
-import android.telephony.DataFailCause;
-import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
-import android.telephony.ServiceState;
-import android.telephony.SignalStrength;
-import android.telephony.SubscriptionManager;
-import android.telephony.emergency.EmergencyNumber;
-import android.telephony.ims.ImsReasonInfo;
-
-import com.android.internal.telephony.IOnSubscriptionsChangedListener;
-import com.android.internal.telephony.IPhoneStateListener;
-import com.android.internal.telephony.ITelephonyRegistry;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class TelephonyRegistryMock extends ITelephonyRegistry.Stub {
-
- private static class Record {
- String callingPackage;
-
- IBinder binder;
-
- IPhoneStateListener callback;
- IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
- IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
-
- int callerUserId;
-
- int events;
-
- int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
- int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
-
- boolean canReadPhoneState;
-
- boolean matchPhoneStateListenerEvent(int events) {
- return (callback != null) && ((events & this.events) != 0);
- }
-
- boolean matchOnSubscriptionsChangedListener() {
- return (onSubscriptionsChangedListenerCallback != null);
- }
-
- boolean matchOnOpportunisticSubscriptionsChangedListener() {
- return (onOpportunisticSubscriptionsChangedListenerCallback != null);
- }
-
-
- @Override
- public String toString() {
- return "{callingPackage=" + callingPackage + " binder=" + binder
- + " callback=" + callback
- + " onSubscriptionsChangedListenerCallback="
- + onSubscriptionsChangedListenerCallback
- + " onOpportunisticSubscriptionsChangedListenerCallback="
- + onOpportunisticSubscriptionsChangedListenerCallback
- + " callerUserId=" + callerUserId + " subId=" + subId + " phoneId=" + phoneId
- + " events=" + Integer.toHexString(events)
- + " canReadPhoneState=" + canReadPhoneState + "}";
- }
- }
-
- private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
- private final ArrayList<Record> mRecords = new ArrayList<Record>();
- private boolean mHasNotifySubscriptionInfoChangedOccurred = false;
- private boolean mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = false;
-
- public TelephonyRegistryMock() {
- }
-
- private void remove(IBinder binder) {
- synchronized (mRecords) {
- final int recordCount = mRecords.size();
- for (int i = 0; i < recordCount; i++) {
- if (mRecords.get(i).binder == binder) {
- mRecords.remove(i);
- return;
- }
- }
- }
- }
-
- private void handleRemoveListLocked() {
- int size = mRemoveList.size();
- if (size > 0) {
- for (IBinder b: mRemoveList) {
- remove(b);
- }
- mRemoveList.clear();
- }
- }
-
-
- @Override
- public void addOnSubscriptionsChangedListener(String callingPackage,
- IOnSubscriptionsChangedListener callback) {
- Record r;
-
- synchronized (mRecords) {
- // register
- find_and_add: {
- IBinder b = callback.asBinder();
- final int N = mRecords.size();
- for (int i = 0; i < N; i++) {
- r = mRecords.get(i);
- if (b == r.binder) {
- break find_and_add;
- }
- }
- r = new Record();
- r.binder = b;
- mRecords.add(r);
- }
-
- r.onSubscriptionsChangedListenerCallback = callback;
- r.callingPackage = callingPackage;
- r.callerUserId = UserHandle.getCallingUserId();
- r.events = 0;
- r.canReadPhoneState = true; // permission has been enforced above
- // Always notify when registration occurs if there has been a notification.
- if (mHasNotifySubscriptionInfoChangedOccurred) {
- try {
- r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
- } catch (RemoteException e) {
- remove(r.binder);
- }
- } else {
- //log("listen oscl: mHasNotifySubscriptionInfoChangedOccurred==false no callback");
- }
- }
-
- }
-
- @Override
- public void addOnOpportunisticSubscriptionsChangedListener(String callingPackage,
- IOnSubscriptionsChangedListener callback) {
- Record r;
-
- synchronized (mRecords) {
- // register
- find_and_add: {
- IBinder b = callback.asBinder();
- final int n = mRecords.size();
- for (int i = 0; i < n; i++) {
- r = mRecords.get(i);
- if (b == r.binder) {
- break find_and_add;
- }
- }
- r = new Record();
- r.binder = b;
- mRecords.add(r);
- }
-
- r.onOpportunisticSubscriptionsChangedListenerCallback = callback;
- r.callingPackage = callingPackage;
- r.callerUserId = UserHandle.getUserHandleForUid(Binder.getCallingUid()).getIdentifier();
- r.events = 0;
- r.canReadPhoneState = true; // permission has been enforced above
- // Always notify when registration occurs if there has been a notification.
- if (mHasNotifyOpportunisticSubscriptionInfoChangedOccurred) {
- try {
- r.onOpportunisticSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
- } catch (RemoteException e) {
- remove(r.binder);
- }
- } else {
- //log("listen oscl: mHasNotifySubscriptionInfoChangedOccurred==false no callback");
- }
- }
-
- }
-
- @Override
- public void removeOnSubscriptionsChangedListener(String pkgForDebug,
- IOnSubscriptionsChangedListener callback) {
- remove(callback.asBinder());
- }
-
- @Override
- public void notifySubscriptionInfoChanged() {
- synchronized (mRecords) {
- if (!mHasNotifySubscriptionInfoChangedOccurred) {
- //log("notifySubscriptionInfoChanged: first invocation mRecords.size="
- // + mRecords.size());
- }
- mHasNotifySubscriptionInfoChangedOccurred = true;
- mRemoveList.clear();
- for (Record r : mRecords) {
- if (r.matchOnSubscriptionsChangedListener()) {
- try {
- r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
- }
- }
- }
- handleRemoveListLocked();
- }
- }
-
- @Override
- public void notifyOpportunisticSubscriptionInfoChanged() {
- synchronized (mRecords) {
- if (!mHasNotifyOpportunisticSubscriptionInfoChangedOccurred) {
- //log("notifySubscriptionInfoChanged: first invocation mRecords.size="
- // + mRecords.size());
- }
- mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = true;
- mRemoveList.clear();
- for (Record r : mRecords) {
- if (r.matchOnOpportunisticSubscriptionsChangedListener()) {
- try {
- r.onOpportunisticSubscriptionsChangedListenerCallback
- .onSubscriptionsChanged();
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
- }
- }
- }
- handleRemoveListLocked();
- }
- }
-
- @Override
- public void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void listenForSubscriber(int subId, String pkg, IPhoneStateListener callback, int events,
- boolean notifyNow) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCallStateForAllSubs(int state, String incomingNumber) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCallState(int phoneId, int subId, int state,
- String incomingNumber) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyServiceStateForPhoneId(int phoneId, int subId, ServiceState state) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifySignalStrengthForPhoneId(int phoneId, int subId,
- SignalStrength signalStrength) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCallForwardingChanged(boolean cfi) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCallForwardingChangedForSubscriber(int subId, boolean cfi) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyDataActivity(int state) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyDataActivityForSubscriber(int subId, int state) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
- String apn, String apnType, LinkProperties linkProperties,
- NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyDataConnectionForSubscriber(int phoneId, int subId, int state,
- boolean isDataConnectivityPossible, String apn, String apnType,
- LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int networkType, boolean roaming) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyDataConnectionFailed(String apnType) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCellLocation(Bundle cellLocation) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyOtaspChanged(int subId, int otaspMode) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCellInfo(List<CellInfo> cellInfo) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyPhysicalChannelConfigurationForSubscriber(int phoneId, int subId,
- List<PhysicalChannelConfig> configs) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyEmergencyNumberList(int phoneId, int subId) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyOutgoingEmergencyCall(int phoneId, int subId,
- EmergencyNumber emergencyNumber) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyOutgoingEmergencySms(int phoneId, int subId,
- EmergencyNumber emergencyNumber) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCallQualityChanged(CallQuality callQuality, int phoneId, int subId,
- int callNetworkType) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
- int foregroundCallState, int backgroundCallState) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
- int preciseDisconnectCause) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyPreciseDataConnectionFailed(int phoneId, int subId,
- String apnType, String apn,
- @DataFailureCause int failCause) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCellInfoForSubscriber(int subId, List<CellInfo> cellInfo) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifySrvccStateChanged(int subId, int state) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyOemHookRawEventForSubscriber(int phoneId, int subId, byte[] rawData) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyCarrierNetworkChange(boolean active) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifySimActivationStateChangedForPhoneId(int phoneId, int subId,
- int activationType, int state) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyUserMobileDataStateChangedForPhoneId(int phoneId, int subId, boolean state) {
- }
-
- @Override
- public void notifyPhoneCapabilityChanged(PhoneCapability capability) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyActiveDataSubIdChanged(int subId) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyRadioPowerStateChanged(int phoneId, int subId, int state) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void notifyImsDisconnectCause(int subId, ImsReasonInfo imsReasonInfo) {
- throw new RuntimeException("Not implemented");
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java b/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java
index 01acf08..c2419b4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/nitz/NewNitzStateMachineImplTest.java
@@ -16,9 +16,14 @@
package com.android.internal.telephony.nitz;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+
import static com.android.internal.telephony.NitzStateMachineTestSupport.ARBITRARY_SYSTEM_CLOCK_TIME;
import static com.android.internal.telephony.NitzStateMachineTestSupport.UNIQUE_US_ZONE_SCENARIO1;
import static com.android.internal.telephony.NitzStateMachineTestSupport.UNITED_KINGDOM_SCENARIO;
+import static com.android.internal.telephony.NitzStateMachineTestSupport.createEmptyTimeSuggestion;
+import static com.android.internal.telephony.NitzStateMachineTestSupport.createEmptyTimeZoneSuggestion;
import static com.android.internal.telephony.NitzStateMachineTestSupport.createTimeSuggestionFromNitzSignal;
import static org.junit.Assert.assertEquals;
@@ -29,6 +34,7 @@
import static org.junit.Assert.assertTrue;
import android.app.timedetector.PhoneTimeSuggestion;
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
import android.util.TimestampedValue;
import com.android.internal.telephony.NitzData;
@@ -37,7 +43,6 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.TimeZoneLookupHelper;
import com.android.internal.telephony.nitz.NewNitzStateMachineImpl.NitzSignalInputFilterPredicate;
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion;
import com.android.internal.util.IndentingPrintWriter;
import org.junit.After;
@@ -52,7 +57,9 @@
private static final int PHONE_ID = 99999;
private static final PhoneTimeZoneSuggestion EMPTY_TIME_ZONE_SUGGESTION =
- new PhoneTimeZoneSuggestion(PHONE_ID);
+ createEmptyTimeZoneSuggestion(PHONE_ID);
+ private static final PhoneTimeSuggestion EMPTY_TIME_SUGGESTION =
+ createEmptyTimeSuggestion(PHONE_ID);
private FakeNewTimeServiceHelper mFakeNewTimeServiceHelper;
private FakeDeviceState mFakeDeviceState;
@@ -85,7 +92,7 @@
mNitzStateMachineImpl = new NewNitzStateMachineImpl(
PHONE_ID, mFakeNitzSignalInputFilter, mRealTimeZoneSuggester,
- mFakeNewTimeServiceHelper, mFakeDeviceState);
+ mFakeNewTimeServiceHelper);
TelephonyTest.logd("NewNitzStateMachineImplTest -Setup!");
}
@@ -208,9 +215,9 @@
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
mRealTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, "" /* countryIsoCode */, nitzSignal);
- assertEquals(PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY,
+ assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY,
expectedTimeZoneSuggestion.getMatchType());
- assertEquals(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET,
+ assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
expectedTimeZoneSuggestion.getQuality());
// Verify the state machine did the right thing.
@@ -252,9 +259,9 @@
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
mRealTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, "" /* countryIsoCode */, nitzSignal);
- assertEquals(PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY,
+ assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY,
expectedTimeZoneSuggestion.getMatchType());
- assertEquals(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET,
+ assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
expectedTimeZoneSuggestion.getQuality());
// Verify the state machine did the right thing.
@@ -307,7 +314,8 @@
// Verify the state machine did the right thing.
// Check the time zone suggestion was withdrawn (time is not currently withdrawn).
- script.verifyOnlyTimeZoneWasSuggestedAndReset(EMPTY_TIME_ZONE_SUGGESTION);
+ script.verifyTimeAndTimeZoneSuggestedAndReset(
+ EMPTY_TIME_SUGGESTION, EMPTY_TIME_ZONE_SUGGESTION);
// Check state that NitzStateMachine must expose.
assertNull(mNitzStateMachineImpl.getCachedNitzData());
@@ -322,8 +330,8 @@
// Simulate airplane mode being turned off.
script.toggleAirplaneMode(false);
- // Verify the time zone suggestion was withdrawn.
- script.verifyOnlyTimeZoneWasSuggestedAndReset(EMPTY_TIME_ZONE_SUGGESTION);
+ // Verify nothing was suggested: The last suggestion was empty so nothing has changed.
+ script.verifyNothingWasSuggested();
// Check the state that NitzStateMachine must expose.
assertNull(mNitzStateMachineImpl.getCachedNitzData());
@@ -399,12 +407,12 @@
// Simulate network being lost.
script.networkUnavailable();
- // Verify the state machine did the right thing.
- // Check the "no NITZ" time zone suggestion is made (time is not currently withdrawn).
+ // Check the "no NITZ" time and time zone suggestions are made.
PhoneTimeZoneSuggestion expectedMiddleTimeZoneSuggestion =
mRealTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, countryIsoCode, null /* nitzSignal */);
- script.verifyOnlyTimeZoneWasSuggestedAndReset(expectedMiddleTimeZoneSuggestion);
+ script.verifyTimeAndTimeZoneSuggestedAndReset(
+ EMPTY_TIME_SUGGESTION, expectedMiddleTimeZoneSuggestion);
// Check state that NitzStateMachine must expose.
assertNull(mNitzStateMachineImpl.getCachedNitzData());
@@ -496,8 +504,6 @@
mFakeDeviceState.ignoreNitz = false;
mFakeDeviceState.nitzUpdateDiffMillis = 2000;
mFakeDeviceState.nitzUpdateSpacingMillis = 1000 * 60 * 10;
-
- mFakeDeviceState.networkCountryIsoForPhone = "";
}
// Initialization methods for setting simulated device state, usually before simulation.
@@ -530,13 +536,12 @@
}
Script countryUnavailable() {
- mNitzStateMachineImpl.handleNetworkCountryCodeUnavailable();
+ mNitzStateMachineImpl.handleCountryUnavailable();
return this;
}
Script countryReceived(String countryIsoCode) {
- mFakeDeviceState.networkCountryIsoForPhone = countryIsoCode;
- mNitzStateMachineImpl.handleNetworkCountryCodeSet(true);
+ mNitzStateMachineImpl.handleCountryDetected(countryIsoCode);
return this;
}
@@ -655,8 +660,10 @@
@Override
public void suggestDeviceTime(PhoneTimeSuggestion timeSuggestion) {
suggestedTimes.set(timeSuggestion);
- // The fake time service just uses the latest suggestion.
- mFakeDeviceState.currentTimeMillis = timeSuggestion.getUtcTime().getValue();
+ if (timeSuggestion.getUtcTime() != null) {
+ // The fake time service just uses the latest suggestion.
+ mFakeDeviceState.currentTimeMillis = timeSuggestion.getUtcTime().getValue();
+ }
}
@Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java b/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java
index cdd30e4..ef1cc0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/nitz/TimeZoneSuggesterImplTest.java
@@ -16,6 +16,14 @@
package com.android.internal.telephony.nitz;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_EMULATOR_ZONE_ID;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+import static android.app.timezonedetector.PhoneTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
+
import static com.android.internal.telephony.NitzStateMachineTestSupport.ARBITRARY_REALTIME_MILLIS;
import static com.android.internal.telephony.NitzStateMachineTestSupport.CZECHIA_SCENARIO;
import static com.android.internal.telephony.NitzStateMachineTestSupport.NEW_ZEALAND_COUNTRY_DEFAULT_ZONE_ID;
@@ -31,6 +39,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.app.timezonedetector.PhoneTimeZoneSuggestion;
import android.util.TimestampedValue;
import com.android.internal.telephony.NitzData;
@@ -39,7 +48,6 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.TimeZoneLookupHelper;
import com.android.internal.telephony.nitz.NewNitzStateMachineImpl.TimeZoneSuggester;
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion;
import org.junit.After;
import org.junit.Before;
@@ -52,7 +60,7 @@
private static final int PHONE_ID = 99999;
private static final PhoneTimeZoneSuggestion EMPTY_TIME_ZONE_SUGGESTION =
- new PhoneTimeZoneSuggestion(PHONE_ID);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID).build();
private FakeDeviceState mFakeDeviceState;
private TimeZoneSuggester mTimeZoneSuggester;
@@ -116,12 +124,11 @@
// will be made.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(US_COUNTRY_DEFAULT_ZONE_ID);
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
@@ -135,10 +142,8 @@
PHONE_ID, "" /* countryIsoCode */,
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
- assertEquals(PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY,
- actualSuggestion.getMatchType());
- assertEquals(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET,
- actualSuggestion.getQuality());
+ assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
+ assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
}
// NITZ alone is not enough to get a result when the country is not available.
@@ -152,12 +157,11 @@
// Country + NITZ is enough for a unique time zone detection result for this scenario.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(),
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
@@ -192,12 +196,11 @@
// will be made.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(US_COUNTRY_DEFAULT_ZONE_ID);
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
@@ -211,10 +214,8 @@
PHONE_ID, "" /* countryIsoCode */,
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
- assertEquals(PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY,
- actualSuggestion.getMatchType());
- assertEquals(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET,
- actualSuggestion.getQuality());
+ assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
+ assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
}
// NITZ alone is not enough to get a result when the country is not available.
@@ -231,10 +232,8 @@
PHONE_ID, scenario.getNetworkCountryIsoCode(),
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
- assertEquals(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET,
- actualSuggestion.getMatchType());
- assertEquals(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET,
- actualSuggestion.getQuality());
+ assertEquals(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, actualSuggestion.getMatchType());
+ assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
List<String> allowedZoneIds = Arrays.asList(NON_UNIQUE_US_ZONE_SCENARIO_ZONES);
assertTrue(allowedZoneIds.contains(actualSuggestion.getZoneId()));
}
@@ -266,12 +265,11 @@
// Country alone is enough to guess the time zone.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
@@ -285,10 +283,8 @@
PHONE_ID, "" /* countryIsoCode */,
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
- assertEquals(PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY,
- actualSuggestion.getMatchType());
- assertEquals(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET,
- actualSuggestion.getQuality());
+ assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
+ assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
}
@@ -303,12 +299,12 @@
// Country + NITZ is enough for both time + time zone detection.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(),
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
@@ -322,12 +318,12 @@
TimestampedValue<NitzData> badNitzSignal =
CZECHIA_SCENARIO.createNitzSignal(mFakeDeviceState.elapsedRealtime());
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(),
badNitzSignal);
@@ -347,12 +343,11 @@
// Country alone is enough to guess the time zone.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
@@ -367,10 +362,8 @@
PHONE_ID, "" /* countryIsoCode */,
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
assertEquals(PHONE_ID, actualSuggestion.getPhoneId());
- assertEquals(PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY,
- actualSuggestion.getMatchType());
- assertEquals(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET,
- actualSuggestion.getQuality());
+ assertEquals(MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY, actualSuggestion.getMatchType());
+ assertEquals(QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET, actualSuggestion.getQuality());
}
@@ -385,12 +378,12 @@
// Country + NITZ is enough for both time + time zone detection.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(),
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime()));
@@ -404,12 +397,12 @@
TimestampedValue<NitzData> badNitzSignal =
UNIQUE_US_ZONE_SCENARIO1.createNitzSignal(mFakeDeviceState.elapsedRealtime());
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(),
badNitzSignal);
@@ -424,12 +417,11 @@
// Country alone is enough to guess the time zone.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
@@ -461,12 +453,11 @@
// Country alone is not enough to guess the time zone.
{
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(US_COUNTRY_DEFAULT_ZONE_ID);
- expectedTimeZoneSuggestion.setMatchType(
- PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedTimeZoneSuggestion.setQuality(
- PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
@@ -513,10 +504,11 @@
originalNitzSignal.getReferenceTimeMillis(), emulatorNitzData);
PhoneTimeZoneSuggestion expectedTimeZoneSuggestion =
- new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedTimeZoneSuggestion.setZoneId(emulatorTimeZoneId);
- expectedTimeZoneSuggestion.setMatchType(PhoneTimeZoneSuggestion.EMULATOR_ZONE_ID);
- expectedTimeZoneSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(emulatorTimeZoneId)
+ .setMatchType(MATCH_TYPE_EMULATOR_ZONE_ID)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), emulatorNitzSignal);
@@ -529,10 +521,13 @@
// countryIsoCode.
{
Scenario scenario = NEW_ZEALAND_DEFAULT_SCENARIO;
- PhoneTimeZoneSuggestion expectedSuggestion = new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedSuggestion.setZoneId(NEW_ZEALAND_COUNTRY_DEFAULT_ZONE_ID);
- expectedSuggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ PhoneTimeZoneSuggestion expectedSuggestion =
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(NEW_ZEALAND_COUNTRY_DEFAULT_ZONE_ID)
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
assertEquals(expectedSuggestion, actualSuggestion);
@@ -543,10 +538,13 @@
Scenario scenario = NEW_ZEALAND_DEFAULT_SCENARIO;
TimestampedValue<NitzData> nitzSignal =
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
- PhoneTimeZoneSuggestion expectedSuggestion = new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedSuggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
- expectedSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ PhoneTimeZoneSuggestion expectedSuggestion =
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
assertEquals(expectedSuggestion, actualSuggestion);
@@ -557,10 +555,13 @@
Scenario scenario = NEW_ZEALAND_OTHER_SCENARIO;
TimestampedValue<NitzData> nitzSignal =
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
- PhoneTimeZoneSuggestion expectedSuggestion = new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedSuggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
- expectedSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ PhoneTimeZoneSuggestion expectedSuggestion =
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
assertEquals(expectedSuggestion, actualSuggestion);
@@ -573,10 +574,13 @@
// Use a scenario that has a different offset than NZ to generate the NITZ signal.
TimestampedValue<NitzData> nitzSignal =
CZECHIA_SCENARIO.createNitzSignal(mFakeDeviceState.elapsedRealtime());
- PhoneTimeZoneSuggestion expectedSuggestion = new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedSuggestion.setZoneId(NEW_ZEALAND_COUNTRY_DEFAULT_ZONE_ID);
- expectedSuggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ PhoneTimeZoneSuggestion expectedSuggestion =
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(NEW_ZEALAND_COUNTRY_DEFAULT_ZONE_ID)
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
assertEquals(expectedSuggestion, actualSuggestion);
@@ -589,11 +593,13 @@
// we cannot get a zone only from the countryIsoCode.
{
Scenario scenario = UNIQUE_US_ZONE_SCENARIO1;
- PhoneTimeZoneSuggestion expectedSuggestion = new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedSuggestion.setZoneId(US_COUNTRY_DEFAULT_ZONE_ID);
- expectedSuggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- expectedSuggestion.setQuality(
- PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
+ PhoneTimeZoneSuggestion expectedSuggestion =
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(US_COUNTRY_DEFAULT_ZONE_ID)
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .setQuality(QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), null /* nitzSignal */);
assertEquals(expectedSuggestion, actualSuggestion);
@@ -604,10 +610,13 @@
Scenario scenario = UNIQUE_US_ZONE_SCENARIO1;
TimestampedValue<NitzData> nitzSignal =
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
- PhoneTimeZoneSuggestion expectedSuggestion = new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedSuggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
- expectedSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ PhoneTimeZoneSuggestion expectedSuggestion =
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
assertEquals(expectedSuggestion, actualSuggestion);
@@ -618,10 +627,13 @@
Scenario scenario = UNIQUE_US_ZONE_SCENARIO2;
TimestampedValue<NitzData> nitzSignal =
scenario.createNitzSignal(mFakeDeviceState.elapsedRealtime());
- PhoneTimeZoneSuggestion expectedSuggestion = new PhoneTimeZoneSuggestion(PHONE_ID);
- expectedSuggestion.setZoneId(scenario.getTimeZoneId());
- expectedSuggestion.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET);
- expectedSuggestion.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
+ PhoneTimeZoneSuggestion expectedSuggestion =
+ new PhoneTimeZoneSuggestion.Builder(PHONE_ID)
+ .setZoneId(scenario.getTimeZoneId())
+ .setMatchType(MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET)
+ .setQuality(QUALITY_SINGLE_ZONE)
+ .build();
+
PhoneTimeZoneSuggestion actualSuggestion = mTimeZoneSuggester.getTimeZoneSuggestion(
PHONE_ID, scenario.getNetworkCountryIsoCode(), nitzSignal);
assertEquals(expectedSuggestion, actualSuggestion);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/nitz/service/PhoneTimeZoneSuggestionTest.java b/tests/telephonytests/src/com/android/internal/telephony/nitz/service/PhoneTimeZoneSuggestionTest.java
deleted file mode 100644
index 54838ae..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/nitz/service/PhoneTimeZoneSuggestionTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2019 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.nitz.service;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import org.junit.Test;
-
-public class PhoneTimeZoneSuggestionTest {
- private static final int PHONE_ID = 99999;
-
- @Test
- public void testEquals() {
- PhoneTimeZoneSuggestion one = new PhoneTimeZoneSuggestion(PHONE_ID);
- assertEquals(one, one);
-
- PhoneTimeZoneSuggestion two = new PhoneTimeZoneSuggestion(PHONE_ID);
- assertEquals(one, two);
- assertEquals(two, one);
-
- PhoneTimeZoneSuggestion three = new PhoneTimeZoneSuggestion(PHONE_ID + 1);
- assertNotEquals(one, three);
- assertNotEquals(three, one);
-
- one.setZoneId("Europe/London");
- assertNotEquals(one, two);
- two.setZoneId("Europe/Paris");
- assertNotEquals(one, two);
- one.setZoneId(two.getZoneId());
- assertEquals(one, two);
-
- one.setMatchType(PhoneTimeZoneSuggestion.EMULATOR_ZONE_ID);
- two.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- assertNotEquals(one, two);
- one.setMatchType(PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY);
- assertEquals(one, two);
-
- one.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
- two.setQuality(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
- assertNotEquals(one, two);
- one.setQuality(PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS);
- assertEquals(one, two);
-
- // DebugInfo must not be considered in equals().
- one.addDebugInfo("Debug info 1");
- two.addDebugInfo("Debug info 2");
- assertEquals(one, two);
- }
-
- @Test
- public void testParcelable() {
- PhoneTimeZoneSuggestion one = new PhoneTimeZoneSuggestion(PHONE_ID);
- assertEquals(one, roundTripParcelable(one));
-
- one.setZoneId("Europe/London");
- one.setMatchType(PhoneTimeZoneSuggestion.EMULATOR_ZONE_ID);
- one.setQuality(PhoneTimeZoneSuggestion.SINGLE_ZONE);
- assertEquals(one, roundTripParcelable(one));
-
- // DebugInfo should also be stored (but is not checked by equals()
- one.addDebugInfo("This is debug info");
- PhoneTimeZoneSuggestion two = roundTripParcelable(one);
- assertEquals(one.getDebugInfo(), two.getDebugInfo());
- }
-
- @SuppressWarnings("unchecked")
- private static <T extends Parcelable> T roundTripParcelable(T one) {
- Parcel parcel = Parcel.obtain();
- parcel.writeTypedObject(one, 0);
- parcel.setDataPosition(0);
-
- T toReturn = (T) parcel.readTypedObject(PhoneTimeZoneSuggestion.CREATOR);
- parcel.recycle();
- return toReturn;
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/nitz/service/TimeZoneDetectionServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/nitz/service/TimeZoneDetectionServiceTest.java
deleted file mode 100644
index f268501..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/nitz/service/TimeZoneDetectionServiceTest.java
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Copyright 2019 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.nitz.service;
-
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.EMULATOR_ZONE_ID;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.MULTIPLE_ZONES_WITH_SAME_OFFSET;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.NETWORK_COUNTRY_AND_OFFSET;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.NETWORK_COUNTRY_ONLY;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.SINGLE_ZONE;
-import static com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.TEST_NETWORK_OFFSET_ONLY;
-import static com.android.internal.telephony.nitz.service.TimeZoneDetectionService.SCORE_HIGH;
-import static com.android.internal.telephony.nitz.service.TimeZoneDetectionService.SCORE_HIGHEST;
-import static com.android.internal.telephony.nitz.service.TimeZoneDetectionService.SCORE_LOW;
-import static com.android.internal.telephony.nitz.service.TimeZoneDetectionService.SCORE_MEDIUM;
-import static com.android.internal.telephony.nitz.service.TimeZoneDetectionService.SCORE_NONE;
-import static com.android.internal.telephony.nitz.service.TimeZoneDetectionService.SCORE_USAGE_THRESHOLD;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.MatchType;
-import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion.Quality;
-import com.android.internal.telephony.nitz.service.TimeZoneDetectionService.QualifiedPhoneTimeZoneSuggestion;
-import com.android.internal.util.IndentingPrintWriter;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-
-/**
- * White-box unit tests for {@link TimeZoneDetectionService}.
- */
-public class TimeZoneDetectionServiceTest {
-
- private static final int PHONE1_ID = 10000;
- private static final int PHONE2_ID = 20000;
-
- // Suggestion test cases are ordered so that each successive one is of the same or higher score
- // than the previous.
- private static final SuggestionTestCase[] TEST_CASES = new SuggestionTestCase[] {
- newTestCase(NETWORK_COUNTRY_ONLY, MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, SCORE_LOW),
- newTestCase(NETWORK_COUNTRY_ONLY, MULTIPLE_ZONES_WITH_SAME_OFFSET, SCORE_MEDIUM),
- newTestCase(NETWORK_COUNTRY_AND_OFFSET, MULTIPLE_ZONES_WITH_SAME_OFFSET, SCORE_MEDIUM),
- newTestCase(NETWORK_COUNTRY_ONLY, SINGLE_ZONE, SCORE_HIGH),
- newTestCase(NETWORK_COUNTRY_AND_OFFSET, SINGLE_ZONE, SCORE_HIGH),
- newTestCase(TEST_NETWORK_OFFSET_ONLY, MULTIPLE_ZONES_WITH_SAME_OFFSET, SCORE_HIGHEST),
- newTestCase(EMULATOR_ZONE_ID, SINGLE_ZONE, SCORE_HIGHEST),
- };
-
- private TimeZoneDetectionService mTimeZoneDetectionService;
- private FakeTimeZoneDetectionServiceHelper mFakeTimeZoneDetectionServiceHelper;
-
- @Before
- public void setUp() {
- mFakeTimeZoneDetectionServiceHelper = new FakeTimeZoneDetectionServiceHelper();
- mTimeZoneDetectionService =
- new TimeZoneDetectionService(mFakeTimeZoneDetectionServiceHelper);
- }
-
- @Test
- public void testEmptySuggestions() {
- PhoneTimeZoneSuggestion phone1TimeZoneSuggestion = createEmptyPhone1Suggestion();
- PhoneTimeZoneSuggestion phone2TimeZoneSuggestion = createEmptyPhone2Suggestion();
- Script script = new Script()
- .initializeTimeZoneDetectionEnabled(true)
- .initializeTimeZoneSetting(true);
-
- script.suggestPhoneTimeZone(phone1TimeZoneSuggestion)
- .verifyTimeZoneNotSet();
-
- // Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedPhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(phone1TimeZoneSuggestion, SCORE_NONE);
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertNull(mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE2_ID));
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
-
- script.suggestPhoneTimeZone(phone2TimeZoneSuggestion)
- .verifyTimeZoneNotSet();
-
- // Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedPhone2ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(phone2TimeZoneSuggestion, SCORE_NONE);
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedPhone2ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE2_ID));
- // Phone 1 should always beat phone 2, all other things being equal.
- assertEquals(expectedPhone1ScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
- }
-
- @Test
- public void testFirstPlausibleSuggestionAcceptedWhenTimeZoneUninitialized() {
- SuggestionTestCase testCase =
- newTestCase(NETWORK_COUNTRY_ONLY, MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS, SCORE_LOW);
- PhoneTimeZoneSuggestion lowQualitySuggestion =
- testCase.createSuggestion(PHONE1_ID, "America/New_York");
- Script script = new Script()
- .initializeTimeZoneDetectionEnabled(true);
-
- // The device is uninitialized.
- script.initializeTimeZoneSetting(false);
-
- // The very first suggestion will be taken.
- script.suggestPhoneTimeZone(lowQualitySuggestion)
- .verifyTimeZoneSetAndReset(lowQualitySuggestion);
-
- // Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(lowQualitySuggestion, testCase.expectedScore);
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
-
- // Another low quality suggestion will be ignored now that the setting is initialized.
- PhoneTimeZoneSuggestion lowQualitySuggestion2 =
- testCase.createSuggestion(PHONE1_ID, "America/Los_Angeles");
- script.suggestPhoneTimeZone(lowQualitySuggestion2)
- .verifyTimeZoneNotSet();
-
- // Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedScoredSuggestion2 =
- new QualifiedPhoneTimeZoneSuggestion(lowQualitySuggestion2, testCase.expectedScore);
- assertEquals(expectedScoredSuggestion2,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedScoredSuggestion2,
- mTimeZoneDetectionService.findBestSuggestionForTests());
- }
-
- @Test
- public void testTogglingTimeZoneDetection() {
- Script script = new Script()
- .initializeTimeZoneSetting(true);
-
- boolean timeZoneDetectionEnabled = false;
- script.initializeTimeZoneDetectionEnabled(timeZoneDetectionEnabled);
-
- for (int i = 0; i < TEST_CASES.length; i++) {
- SuggestionTestCase testCase = TEST_CASES[i];
-
- PhoneTimeZoneSuggestion suggestion =
- testCase.createSuggestion(PHONE1_ID, "Europe/London");
- script.suggestPhoneTimeZone(suggestion);
-
- // When time zone detection is already enabled the suggestion (if it scores highly
- // enough) should be set immediately.
- if (timeZoneDetectionEnabled) {
- if (testCase.expectedScore >= SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(suggestion);
- } else {
- script.verifyTimeZoneNotSet();
- }
- } else {
- script.verifyTimeZoneNotSet();
- }
-
- // Assert internal service state.
- QualifiedPhoneTimeZoneSuggestion expectedScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(suggestion, testCase.expectedScore);
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
-
- // Now toggle the time zone detection setting: when it is toggled to on and the most
- // recent suggestion scores highly enough, the time zone should be set.
- timeZoneDetectionEnabled = !timeZoneDetectionEnabled;
- script.timeZoneDetectionEnabled(timeZoneDetectionEnabled);
- if (timeZoneDetectionEnabled) {
- if (testCase.expectedScore >= SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(suggestion);
- } else {
- script.verifyTimeZoneNotSet();
- }
- } else {
- script.verifyTimeZoneNotSet();
- }
-
- // Assert internal service state.
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
- }
- }
-
- @Test
- public void testSuggestionsSinglePhone() {
- Script script = new Script()
- .initializeTimeZoneDetectionEnabled(true)
- .initializeTimeZoneSetting(true);
-
- for (SuggestionTestCase testCase : TEST_CASES) {
- makePhone1SuggestionAndCheckState(script, testCase);
- }
-
- /*
- * This is the same test as above but the test cases are in
- * reverse order of their expected score. New suggestions always replace previous ones:
- * there's effectively no history and so ordering shouldn't make any difference.
- */
-
- // Each test case will have the same or lower score than the last.
- ArrayList<SuggestionTestCase> descendingCasesByScore =
- new ArrayList<>(Arrays.asList(TEST_CASES));
- Collections.reverse(descendingCasesByScore);
-
- for (SuggestionTestCase testCase : descendingCasesByScore) {
- makePhone1SuggestionAndCheckState(script, testCase);
- }
- }
-
- private void makePhone1SuggestionAndCheckState(Script script, SuggestionTestCase testCase) {
- String zoneId = "Europe/London";
- PhoneTimeZoneSuggestion zonePhone1Suggestion = testCase.createSuggestion(PHONE1_ID, zoneId);
- QualifiedPhoneTimeZoneSuggestion expectedZonePhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(zonePhone1Suggestion, testCase.expectedScore);
-
- script.suggestPhoneTimeZone(zonePhone1Suggestion);
- if (testCase.expectedScore >= SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(zonePhone1Suggestion);
- } else {
- script.verifyTimeZoneNotSet();
- }
-
- // Assert internal service state.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
- }
-
- /**
- * Tries a set of test cases to see if the phone with the lowest ID is given preference. This
- * test also confirms that the time zone setting would only be set if a suggestion is of
- * sufficient quality.
- */
- @Test
- public void testMultiplePhoneSuggestionScoringAndPhoneIdBias() {
- String[] zoneIds = { "Europe/London", "Europe/Paris" };
- PhoneTimeZoneSuggestion emptyPhone1Suggestion = createEmptyPhone1Suggestion();
- PhoneTimeZoneSuggestion emptyPhone2Suggestion = createEmptyPhone2Suggestion();
- QualifiedPhoneTimeZoneSuggestion expectedEmptyPhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(emptyPhone1Suggestion, SCORE_NONE);
- QualifiedPhoneTimeZoneSuggestion expectedEmptyPhone2ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(emptyPhone2Suggestion, SCORE_NONE);
-
- Script script = new Script()
- .initializeTimeZoneDetectionEnabled(true)
- .initializeTimeZoneSetting(true)
- // Initialize the latest suggestions as empty so we don't need to worry about nulls
- // below for the first loop.
- .suggestPhoneTimeZone(emptyPhone1Suggestion)
- .suggestPhoneTimeZone(emptyPhone2Suggestion)
- .resetState();
-
- for (SuggestionTestCase testCase : TEST_CASES) {
- PhoneTimeZoneSuggestion zonePhone1Suggestion =
- testCase.createSuggestion(PHONE1_ID, zoneIds[0]);
- PhoneTimeZoneSuggestion zonePhone2Suggestion =
- testCase.createSuggestion(PHONE2_ID, zoneIds[1]);
- QualifiedPhoneTimeZoneSuggestion expectedZonePhone1ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(zonePhone1Suggestion,
- testCase.expectedScore);
- QualifiedPhoneTimeZoneSuggestion expectedZonePhone2ScoredSuggestion =
- new QualifiedPhoneTimeZoneSuggestion(zonePhone2Suggestion,
- testCase.expectedScore);
-
- // Start the test by making a suggestion for phone 1.
- script.suggestPhoneTimeZone(zonePhone1Suggestion);
- if (testCase.expectedScore >= SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(zonePhone1Suggestion);
- } else {
- script.verifyTimeZoneNotSet();
- }
-
- // Assert internal service state.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedEmptyPhone2ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE2_ID));
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
-
- // Phone 2 then makes an identical suggestion. Phone 1's suggestion should still "win"
- // if it is above the required threshold.
- script.suggestPhoneTimeZone(zonePhone2Suggestion);
- if (testCase.expectedScore >= SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(zonePhone1Suggestion);
- } else {
- script.verifyTimeZoneNotSet();
- }
-
- // Assert internal service state.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedZonePhone2ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE2_ID));
- // Phone 1 should always beat phone 2, all other things being equal.
- assertEquals(expectedZonePhone1ScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
-
- // Withdrawing phone 1's suggestion should leave phone 2 as the new winner. Since the
- // zoneId is different, the time zone setting should be updated.
- script.suggestPhoneTimeZone(emptyPhone1Suggestion);
- if (testCase.expectedScore >= SCORE_USAGE_THRESHOLD) {
- script.verifyTimeZoneSetAndReset(zonePhone2Suggestion);
- } else {
- script.verifyTimeZoneNotSet();
- }
-
- // Assert internal service state.
- assertEquals(expectedEmptyPhone1ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedZonePhone2ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE2_ID));
- assertEquals(expectedZonePhone2ScoredSuggestion,
- mTimeZoneDetectionService.findBestSuggestionForTests());
-
- // Reset the state for the next loop.
- script.suggestPhoneTimeZone(emptyPhone2Suggestion)
- .verifyTimeZoneNotSet();
- assertEquals(expectedEmptyPhone1ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE1_ID));
- assertEquals(expectedEmptyPhone2ScoredSuggestion,
- mTimeZoneDetectionService.getLatestPhoneSuggestion(PHONE2_ID));
- }
- }
-
- /**
- * The {@link TimeZoneDetectionService.Helper} is left to detect whether changing the the time
- * zone is actually necessary. This test proves that the service doesn't assume it knows the
- * current setting.
- */
- @Test
- public void testTimeZoneDetectionServiceDoesNotAssumeCurrentSetting() {
- Script script = new Script()
- .initializeTimeZoneDetectionEnabled(true);
-
- SuggestionTestCase testCase =
- newTestCase(NETWORK_COUNTRY_AND_OFFSET, SINGLE_ZONE, SCORE_HIGH);
- PhoneTimeZoneSuggestion losAngelesSuggestion =
- testCase.createSuggestion(PHONE1_ID, "America/Los_Angeles");
- PhoneTimeZoneSuggestion newYorkSuggestion =
- testCase.createSuggestion(PHONE1_ID, "America/New_York");
-
- // Initialization.
- script.suggestPhoneTimeZone(losAngelesSuggestion)
- .verifyTimeZoneSetAndReset(losAngelesSuggestion);
- // Suggest it again - it should be set.
- script.suggestPhoneTimeZone(losAngelesSuggestion)
- .verifyTimeZoneSetAndReset(losAngelesSuggestion);
-
- // Toggling time zone detection should set it.
- script.timeZoneDetectionEnabled(false)
- .timeZoneDetectionEnabled(true)
- .verifyTimeZoneSetAndReset(losAngelesSuggestion);
-
- // Simulate a user turning detection off, a new suggestion being made, and the user turning
- // it on again.
- script.timeZoneDetectionEnabled(false)
- .suggestPhoneTimeZone(newYorkSuggestion)
- .verifyTimeZoneNotSet();
- // Latest suggestion should be used.
- script.timeZoneDetectionEnabled(true)
- .verifyTimeZoneSetAndReset(newYorkSuggestion);
- }
-
- private static PhoneTimeZoneSuggestion createEmptyPhone1Suggestion() {
- return new PhoneTimeZoneSuggestion(PHONE1_ID);
- }
-
- private static PhoneTimeZoneSuggestion createEmptyPhone2Suggestion() {
- return new PhoneTimeZoneSuggestion(PHONE2_ID);
- }
-
- class FakeTimeZoneDetectionServiceHelper implements TimeZoneDetectionService.Helper {
-
- private Listener mListener;
- private boolean mTimeZoneDetectionEnabled;
- private boolean mTimeZoneInitialized = false;
- private TestState<PhoneTimeZoneSuggestion> mTimeZoneSuggestion = new TestState<>();
-
- @Override
- public void setListener(Listener listener) {
- this.mListener = listener;
- }
-
- @Override
- public boolean isTimeZoneDetectionEnabled() {
- return mTimeZoneDetectionEnabled;
- }
-
- @Override
- public boolean isTimeZoneSettingInitialized() {
- return mTimeZoneInitialized;
- }
-
- @Override
- public void setDeviceTimeZoneFromSuggestion(PhoneTimeZoneSuggestion timeZoneSuggestion) {
- mTimeZoneInitialized = true;
- mTimeZoneSuggestion.set(timeZoneSuggestion);
- }
-
- @Override
- public void dumpState(PrintWriter pw) {
- // No-op for fake
- }
-
- @Override
- public void dumpLogs(IndentingPrintWriter ipw) {
- // No-op for fake
- }
-
- void initializeTimeZoneDetectionEnabled(boolean enabled) {
- mTimeZoneDetectionEnabled = enabled;
- }
-
- void initializeTimeZone(boolean initialized) {
- mTimeZoneInitialized = initialized;
- }
-
- void simulateTimeZoneDetectionEnabled(boolean enabled) {
- mTimeZoneDetectionEnabled = enabled;
- mListener.onTimeZoneDetectionChange(enabled);
- }
-
- void assertTimeZoneNotSet() {
- mTimeZoneSuggestion.assertHasNotBeenSet();
- }
-
- void assertTimeZoneSuggested(PhoneTimeZoneSuggestion timeZoneSuggestion) {
- mTimeZoneSuggestion.assertHasBeenSet();
- mTimeZoneSuggestion.assertChangeCount(1);
- mTimeZoneSuggestion.assertLatestEquals(timeZoneSuggestion);
- }
-
- void commitAllChanges() {
- mTimeZoneSuggestion.commitLatest();
- }
- }
-
- /** Some piece of state that tests want to track. */
- private static class TestState<T> {
- private T mInitialValue;
- private LinkedList<T> mValues = new LinkedList<>();
-
- void init(T value) {
- mValues.clear();
- mInitialValue = value;
- }
-
- void set(T value) {
- mValues.addFirst(value);
- }
-
- boolean hasBeenSet() {
- return mValues.size() > 0;
- }
-
- void assertHasNotBeenSet() {
- assertFalse(hasBeenSet());
- }
-
- void assertHasBeenSet() {
- assertTrue(hasBeenSet());
- }
-
- void commitLatest() {
- if (hasBeenSet()) {
- mInitialValue = mValues.getLast();
- mValues.clear();
- }
- }
-
- void assertLatestEquals(T expected) {
- assertEquals(expected, getLatest());
- }
-
- void assertChangeCount(int expectedCount) {
- assertEquals(expectedCount, mValues.size());
- }
-
- public T getLatest() {
- if (hasBeenSet()) {
- return mValues.getFirst();
- }
- return mInitialValue;
- }
- }
-
- /**
- * A "fluent" class allows reuse of code in tests: initialization, simulation and verification
- * logic.
- */
- private class Script {
-
- Script initializeTimeZoneDetectionEnabled(boolean enabled) {
- mFakeTimeZoneDetectionServiceHelper.initializeTimeZoneDetectionEnabled(enabled);
- return this;
- }
-
- Script initializeTimeZoneSetting(boolean initialized) {
- mFakeTimeZoneDetectionServiceHelper.initializeTimeZone(initialized);
- return this;
- }
-
- Script timeZoneDetectionEnabled(boolean timeZoneDetectionEnabled) {
- mFakeTimeZoneDetectionServiceHelper.simulateTimeZoneDetectionEnabled(
- timeZoneDetectionEnabled);
- return this;
- }
-
- /** Simulates the time zone detection service receiving a phone-originated suggestion. */
- Script suggestPhoneTimeZone(PhoneTimeZoneSuggestion phoneTimeZoneSuggestion) {
- mTimeZoneDetectionService.suggestPhoneTimeZone(phoneTimeZoneSuggestion);
- return this;
- }
-
- Script verifyTimeZoneNotSet() {
- mFakeTimeZoneDetectionServiceHelper.assertTimeZoneNotSet();
- return this;
- }
-
- Script verifyTimeZoneSetAndReset(PhoneTimeZoneSuggestion timeZoneSuggestion) {
- mFakeTimeZoneDetectionServiceHelper.assertTimeZoneSuggested(timeZoneSuggestion);
- mFakeTimeZoneDetectionServiceHelper.commitAllChanges();
- return this;
- }
-
- Script resetState() {
- mFakeTimeZoneDetectionServiceHelper.commitAllChanges();
- return this;
- }
- }
-
- private static class SuggestionTestCase {
- public final int matchType;
- public final int quality;
- public final int expectedScore;
-
- SuggestionTestCase(int matchType, int quality, int expectedScore) {
- this.matchType = matchType;
- this.quality = quality;
- this.expectedScore = expectedScore;
- }
-
- private PhoneTimeZoneSuggestion createSuggestion(int phoneId, String zoneId) {
- PhoneTimeZoneSuggestion suggestion = new PhoneTimeZoneSuggestion(phoneId);
- suggestion.setZoneId(zoneId);
- suggestion.setMatchType(matchType);
- suggestion.setQuality(quality);
- return suggestion;
- }
- }
-
- private static SuggestionTestCase newTestCase(
- @MatchType int matchType, @Quality int quality, int expectedScore) {
- return new SuggestionTestCase(matchType, quality, expectedScore);
- }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index 804bdf1..336267c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -39,7 +39,6 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
-import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.uicc.euicc.EuiccCard;
@@ -52,6 +51,7 @@
import java.util.ArrayList;
+
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class UiccControllerTest extends TelephonyTest {
@@ -109,8 +109,7 @@
// for testing we pretend slotIndex is set. In reality it would be invalid on older versions
// (before 1.2) of hal
mIccCardStatus.physicalSlotIndex = 0;
- mUiccControllerUT = UiccController.make(mContext,
- new CommandsInterface[]{mSimulatedCommands});
+ mUiccControllerUT = UiccController.make(mContext);
// reset sLastSlotStatus so that onGetSlotStatusDone always sees a change in the slot status
mUiccControllerUT.sLastSlotStatus = null;
processAllMessages();
@@ -131,8 +130,7 @@
com.android.internal.R.array.non_removable_euicc_slots,
nonRemovableEuiccSlots);
replaceInstance(UiccController.class, "mInstance", null, null);
- mUiccControllerUT = UiccController.make(mContext,
- new CommandsInterface[]{mSimulatedCommands});
+ mUiccControllerUT = UiccController.make(mContext);
processAllMessages();
}