summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:26:36 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:26:36 +0000
commit4b0cd89280695b4aa5b527534e374d098a352ff3 (patch)
tree6ab377c21a9227c077fe7707c570cc95a6f93968
parent60f33a6fe4abdd20675c96340016197c52d8f631 (diff)
parent8eaedf7cc2d20d4f81a967c6a4af12aec1bfff7e (diff)
downloadAlternativeNetworkAccess-android14-mainline-networking-release.tar.gz
Change-Id: Id2c084bd08c60935483bbfbc05c12efe1a365ae0
-rw-r--r--Android.bp12
-rw-r--r--AndroidManifest.xml4
-rw-r--r--OWNERS7
-rw-r--r--PREUPLOAD.cfg10
-rw-r--r--src/com/android/ons/ONSNetworkScanCtlr.java9
-rw-r--r--src/com/android/ons/ONSProfileActivator.java130
-rw-r--r--src/com/android/ons/ONSProfileConfigurator.java27
-rw-r--r--src/com/android/ons/ONSProfileDownloader.java72
-rw-r--r--src/com/android/ons/ONSProfileSelector.java97
-rw-r--r--src/com/android/ons/ONSStats.java200
-rw-r--r--src/com/android/ons/ONSStatsInfo.java125
-rw-r--r--src/com/android/ons/OpportunisticNetworkService.java24
-rw-r--r--tests/src/com/android/ons/ONSNetworkScanCtlrTest.java26
-rw-r--r--tests/src/com/android/ons/ONSProfileActivatorTest.java325
-rw-r--r--tests/src/com/android/ons/ONSProfileConfiguratorTest.java18
-rw-r--r--tests/src/com/android/ons/ONSProfileDownloaderTest.java148
-rw-r--r--tests/src/com/android/ons/ONSProfileSelectorTest.java348
-rw-r--r--tests/src/com/android/ons/ONSStatsInfoTest.java96
-rw-r--r--tests/src/com/android/ons/ONSStatsTest.java317
-rw-r--r--tests/src/com/android/ons/OpportunisticNetworkServiceTest.java18
20 files changed, 1707 insertions, 306 deletions
diff --git a/Android.bp b/Android.bp
index 7268d27..fe33720 100644
--- a/Android.bp
+++ b/Android.bp
@@ -27,10 +27,20 @@ android_app {
"telephony-common",
"app-compat-annotations",
],
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java",
+ ":statslog-ons-java-gen",
+ ],
aaptflags: ["--auto-add-overlay"],
certificate: "platform",
optimize: {
proguard_flags_files: ["proguard.flags"],
},
}
+
+genrule {
+ name: "statslog-ons-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module ons --javaPackage com.android.ons --javaClass OnsStatsLog",
+ out: ["com/android/ons/OnsStatsLog.java"],
+}
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0141961..fb2346f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -21,8 +21,8 @@
android:process="com.android.phone"
android:sharedUserId="android.uid.phone">
- <protected-broadcast android:name="com.android.ons.action.DOWNLOAD" />
- <protected-broadcast android:name="com.android.ons.action.CONFIG" />
+ <protected-broadcast android:name="com.android.ons.action.ESIM_DOWNLOAD" />
+ <protected-broadcast android:name="com.android.ons.action.ESIM_CONFIG" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/OWNERS b/OWNERS
index f4fd81c..6927b2e 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,6 +1 @@
-# Default code reviewers picked from top 3 or more developers.
-# Please update this list if you find better candidates.
-sasindran@google.com
-rgreenwalt@google.com
-amruthr@google.com
-jacknudelman@google.com \ No newline at end of file
+file:platform/frameworks/opt/telephony:/OWNERS
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index de2615a..de4cf97 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -20,14 +20,4 @@ bpfmt = -d
[Hook Scripts]
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
-strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT}
-
-hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
-
-hidden_api_txt_exclude_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/exclude.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
-
ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
-
-owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
-
-shell_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^packages/Shell/" \ No newline at end of file
diff --git a/src/com/android/ons/ONSNetworkScanCtlr.java b/src/com/android/ons/ONSNetworkScanCtlr.java
index 97ef770..e14148f 100644
--- a/src/com/android/ons/ONSNetworkScanCtlr.java
+++ b/src/com/android/ons/ONSNetworkScanCtlr.java
@@ -40,10 +40,10 @@ import com.android.telephony.Rlog;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.stream.Collectors;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/**
* Network Scan controller class which will scan for the specific bands as requested and
@@ -266,11 +266,16 @@ public class ONSNetworkScanCtlr {
}
/* get mcc mnc from cell info if the cell is for LTE */
- private String getMccMnc(CellInfo cellInfo) {
+ @VisibleForTesting
+ protected String getMccMnc(CellInfo cellInfo) {
if (cellInfo instanceof CellInfoLte) {
return ((CellInfoLte) cellInfo).getCellIdentity().getMccString()
+ ((CellInfoLte) cellInfo).getCellIdentity().getMncString();
}
+ else if (cellInfo instanceof CellInfoNr) {
+ return ((CellInfoNr) cellInfo).getCellIdentity().getMccString()
+ + ((CellInfoNr) cellInfo).getCellIdentity().getMncString();
+ }
return null;
}
diff --git a/src/com/android/ons/ONSProfileActivator.java b/src/com/android/ons/ONSProfileActivator.java
index 5325b8f..05228b8 100644
--- a/src/com/android/ons/ONSProfileActivator.java
+++ b/src/com/android/ons/ONSProfileActivator.java
@@ -35,6 +35,7 @@ import android.telephony.euicc.EuiccManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.ons.ONSProfileDownloader.DownloadRetryResultCode;
import java.util.ArrayList;
import java.util.List;
@@ -48,8 +49,6 @@ import java.util.Random;
public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfigListener,
ONSProfileDownloader.IONSProfileDownloaderListener {
- public static final String ACTION_CARRIER_CONFIG_CHANGED =
- "android.telephony.action.CARRIER_CONFIG_CHANGED";
private static final String TAG = ONSProfileActivator.class.getName();
private final Context mContext;
private final SubscriptionManager mSubManager;
@@ -59,13 +58,14 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
private final ONSProfileConfigurator mONSProfileConfig;
private final ONSProfileDownloader mONSProfileDownloader;
private final ConnectivityManager mConnectivityManager;
+ private final ONSStats mONSStats;
@VisibleForTesting protected boolean mIsInternetConnAvailable = false;
@VisibleForTesting protected boolean mRetryDownloadWhenNWConnected = false;
- private int mDownloadRetryCount = 0;
+ @VisibleForTesting protected int mDownloadRetryCount = 0;
@VisibleForTesting protected static final int REQUEST_CODE_DOWNLOAD_RETRY = 2;
- public ONSProfileActivator(Context context) {
+ public ONSProfileActivator(Context context, ONSStats onsStats) {
mContext = context;
mSubManager = mContext.getSystemService(SubscriptionManager.class);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
@@ -78,7 +78,7 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
//Monitor internet connection.
mConnectivityManager = context.getSystemService(ConnectivityManager.class);
-
+ mONSStats = onsStats;
NetworkRequest request = new NetworkRequest.Builder().addCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
mConnectivityManager.registerNetworkCallback(request, new NetworkCallback());
@@ -92,7 +92,7 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
TelephonyManager telephonyManager, CarrierConfigManager carrierConfigMgr,
EuiccManager euiccManager, ConnectivityManager connManager,
ONSProfileConfigurator onsProfileConfigurator,
- ONSProfileDownloader onsProfileDownloader) {
+ ONSProfileDownloader onsProfileDownloader, ONSStats onsStats) {
mContext = mockContext;
mSubManager = subscriptionManager;
mTelephonyManager = telephonyManager;
@@ -101,6 +101,7 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
mConnectivityManager = connManager;
mONSProfileConfig = onsProfileConfigurator;
mONSProfileDownloader = onsProfileDownloader;
+ mONSStats = onsStats;
}
ONSProfileConfigurator getONSProfileConfigurator() {
@@ -116,7 +117,9 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
public void handleMessage(Message msg) {
switch (msg.what) {
case REQUEST_CODE_DOWNLOAD_RETRY: {
- provisionCBRS();
+ Result res = provisionCBRS();
+ Log.d(TAG, res.toString());
+ mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res));
}
break;
}
@@ -127,19 +130,24 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
* Called when SIM state changes. Triggers CBRS Auto provisioning.
*/
public Result handleCarrierConfigChange() {
- /*final int simState = mTelephonyManager.getSimState();
- if (simState != TelephonyManager.SIM_STATE_READY) {
- return Result.ERR_SIM_NOT_READY;
- }*/
-
Result res = provisionCBRS();
Log.d(TAG, res.toString());
+ mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res));
+
+ // Reset mDownloadRetryCount as carrier config change event is received. Either new SIM card
+ // is inserted or carrier config values are updated.
+ if (res == Result.DOWNLOAD_REQUESTED || res == Result.SUCCESS) {
+ mDownloadRetryCount = 0;
+ }
+
return res;
}
@Override
public void onOppSubscriptionDeleted(int pSIMId) {
- provisionCBRS();
+ Result res = provisionCBRS();
+ Log.d(TAG, res.toString());
+ mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res));
}
/**
@@ -165,12 +173,13 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
//Check the number of active subscriptions.
List<SubscriptionInfo> activeSubInfos = mSubManager.getActiveSubscriptionInfoList();
+ if (activeSubInfos == null || activeSubInfos.size() <= 0) {
+ return Result.ERR_NO_SIM_INSERTED;
+ }
int activeSubCount = activeSubInfos.size();
Log.d(TAG, "Active subscription count:" + activeSubCount);
- if (activeSubCount <= 0) {
- return Result.ERR_NO_SIM_INSERTED;
- } else if (activeSubCount == 1) {
+ if (activeSubCount == 1) {
SubscriptionInfo pSubInfo = activeSubInfos.get(0);
if (pSubInfo.isOpportunistic()) {
//Only one SIM is active and its opportunistic SIM.
@@ -273,8 +282,16 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
}
//Opportunistic subscription not found. Trigger Download.
- mONSProfileDownloader.downloadProfile(primaryCBRSSubInfo.getSubscriptionId());
- return Result.SUCCESS;
+ ONSProfileDownloader.DownloadProfileResult res = mONSProfileDownloader.downloadProfile(
+ primaryCBRSSubInfo.getSubscriptionId());
+
+ switch (res) {
+ case DUPLICATE_REQUEST: return Result.ERR_DUPLICATE_DOWNLOAD_REQUEST;
+ case INVALID_SMDP_ADDRESS: return Result.ERR_INVALID_CARRIER_CONFIG;
+ case SUCCESS: return Result.DOWNLOAD_REQUESTED;
+ }
+
+ return Result.ERR_UNKNOWN;
}
@Override
@@ -284,23 +301,37 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
primarySubId);
if (opportunisticESIM == null) {
Log.e(TAG, "Downloaded Opportunistic eSIM not found. Unable to group with pSIM");
+ mONSStats.logEvent(new ONSStatsInfo()
+ .setProvisioningResult(Result.ERR_DOWNLOADED_ESIM_NOT_FOUND)
+ .setPrimarySimSubId(primarySubId)
+ .setWifiConnected(isWiFiConnected()));
return;
}
SubscriptionInfo pSIMSubInfo = mSubManager.getActiveSubscriptionInfo(primarySubId);
if (pSIMSubInfo != null) {
+ // Group with same Primary SIM for which eSIM is downloaded.
mONSProfileConfig.groupWithPSIMAndSetOpportunistic(
opportunisticESIM, pSIMSubInfo.getGroupUuid());
Log.d(TAG, "eSIM downloaded and configured successfully");
+ mONSStats.logEvent(new ONSStatsInfo()
+ .setProvisioningResult(Result.SUCCESS)
+ .setRetryCount(mDownloadRetryCount)
+ .setWifiConnected(isWiFiConnected()));
} else {
Log.d(TAG, "ESIM downloaded but pSIM is not active or removed");
+ mONSStats.logEvent(new ONSStatsInfo()
+ .setProvisioningResult(Result.ERR_PSIM_NOT_FOUND)
+ .setOppSimCarrierId(opportunisticESIM.getCarrierId())
+ .setWifiConnected(isWiFiConnected()));
}
}
@Override
- public void onDownloadError(ONSProfileDownloader.DownloadRetryOperationCode operationCode,
- int pSIMSubId) {
- switch (operationCode) {
+ public void onDownloadError(int pSIMSubId, DownloadRetryResultCode resultCode,
+ int detailedErrorCode) {
+ boolean logStats = true;
+ switch (resultCode) {
case ERR_MEMORY_FULL: {
//eUICC Memory full occurred while downloading opportunistic eSIM.
@@ -340,34 +371,48 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
break;
case ERR_RETRY_DOWNLOAD: {
- startBackoffTimer(pSIMSubId, mDownloadRetryCount);
+ if (startBackoffTimer(pSIMSubId)) {
+ // do not log the atom if download retry has not reached max limit.
+ logStats = false;
+ }
}
break;
-
- case ERR_UNRESOLVABLE: {
- //Stop download until SIM change or device reboot.
+ default: {
+ // Stop download until SIM change or device reboot.
+ Log.e(TAG, "Download failed with cause=" + resultCode);
}
}
+ if (logStats) {
+ mONSStats.logEvent(new ONSStatsInfo()
+ .setDownloadResult(resultCode)
+ .setPrimarySimSubId(pSIMSubId)
+ .setRetryCount(mDownloadRetryCount)
+ .setDetailedErrCode(detailedErrorCode)
+ .setWifiConnected(isWiFiConnected()));
+ }
}
/**
* Called when eSIM download fails. Listener is called after a delay based on retry count with
* the error code: BACKOFF_TIMER_EXPIRED
- * @param pSIMSubId
- * @param retryCount
+ *
+ * @param pSIMSubId Primary Subscription ID
+ * @return true if backoff timer starts; otherwise false.
*/
@VisibleForTesting
- protected void startBackoffTimer(int pSIMSubId, int retryCount) {
+ protected boolean startBackoffTimer(int pSIMSubId) {
//retry logic
- retryCount++;
- Log.e(TAG, "Download retry count :" + retryCount);
- if (retryCount >= getDownloadRetryMaxAttemptsVal(pSIMSubId)) {
+ mDownloadRetryCount++;
+ Log.e(TAG, "Download retry count :" + mDownloadRetryCount);
+
+ //Stop download retry if number of retries exceeded max configured value.
+ if (mDownloadRetryCount > getDownloadRetryMaxAttemptsVal(pSIMSubId)) {
Log.e(TAG, "Max download retry attempted. Stopping retry");
- return;
+ return false;
}
int backoffTimerVal = getDownloadRetryBackOffTimerVal(pSIMSubId);
- int delay = calculateBackoffDelay(retryCount, backoffTimerVal);
+ int delay = calculateBackoffDelay(mDownloadRetryCount, backoffTimerVal);
Message retryMsg = new Message();
retryMsg.what = REQUEST_CODE_DOWNLOAD_RETRY;
@@ -375,6 +420,7 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
mHandler.sendMessageDelayed(retryMsg, delay);
Log.d(TAG, "Download failed. Retry after :" + delay + "MilliSecs");
+ return true;
}
@VisibleForTesting
@@ -405,7 +451,7 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
* attempts will not be made until next device reboot.
*
* @param subscriptionId subscription Id of the primary SIM.
- * @return
+ * @return integer value for maximum allowed retry attempts.
*/
private int getDownloadRetryMaxAttemptsVal(int subscriptionId) {
PersistableBundle config = mCarrierConfigMgr.getConfigForSubId(subscriptionId);
@@ -506,7 +552,9 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
Log.d(TAG, "Internet connection available");
mIsInternetConnAvailable = true;
if (mRetryDownloadWhenNWConnected) {
- provisionCBRS();
+ Result res = provisionCBRS();
+ Log.d(TAG, res.toString());
+ mONSStats.logEvent(new ONSStatsInfo().setProvisioningResult(res));
}
}
@@ -518,20 +566,28 @@ public class ONSProfileActivator implements ONSProfileConfigurator.ONSProfConfig
}
}
+ /**
+ * Enum to map the results of the CBRS provisioning. The order of the defined enums must be kept
+ * intact and new entries should be appended at the end of the list.
+ */
public enum Result {
SUCCESS,
+ DOWNLOAD_REQUESTED,
ERR_SWITCHING_TO_DUAL_SIM_MODE,
ERR_AUTO_PROVISIONING_DISABLED,
ERR_ESIM_NOT_SUPPORTED,
ERR_MULTISIM_NOT_SUPPORTED,
ERR_CARRIER_DOESNT_SUPPORT_CBRS,
- ERR_DUAL_ACTIVE_SUBSCRIPTIONS,//Both the slots have primary SIMs
+ ERR_DUAL_ACTIVE_SUBSCRIPTIONS,
ERR_NO_SIM_INSERTED,
ERR_SINGLE_ACTIVE_OPPORTUNISTIC_SIM,
ERR_CANNOT_SWITCH_TO_DUAL_SIM_MODE,
- ERR_SIM_NOT_READY,
ERR_WAITING_FOR_INTERNET_CONNECTION,
ERR_WAITING_FOR_WIFI_CONNECTION,
+ ERR_DUPLICATE_DOWNLOAD_REQUEST,
+ ERR_INVALID_CARRIER_CONFIG,
+ ERR_DOWNLOADED_ESIM_NOT_FOUND,
+ ERR_PSIM_NOT_FOUND,
ERR_UNKNOWN;
}
}
diff --git a/src/com/android/ons/ONSProfileConfigurator.java b/src/com/android/ons/ONSProfileConfigurator.java
index 6026a95..84bcdad 100644
--- a/src/com/android/ons/ONSProfileConfigurator.java
+++ b/src/com/android/ons/ONSProfileConfigurator.java
@@ -127,10 +127,15 @@ public class ONSProfileConfigurator {
@VisibleForTesting
protected void groupWithPSIMAndSetOpportunistic(
SubscriptionInfo opportunisticESIM, ParcelUuid groupUuid) {
- Log.d(TAG, "Grouping opportunistc eSIM and CBRS pSIM");
- ArrayList<Integer> subList = new ArrayList<>();
- subList.add(opportunisticESIM.getSubscriptionId());
- mSubscriptionManager.addSubscriptionsIntoGroup(subList, groupUuid);
+ if (groupUuid != null && groupUuid.equals(opportunisticESIM.getGroupUuid())) {
+ Log.d(TAG, "opportunistc eSIM and CBRS pSIM already grouped");
+ } else {
+ Log.d(TAG, "Grouping opportunistc eSIM and CBRS pSIM");
+ ArrayList<Integer> subList = new ArrayList<>();
+ subList.add(opportunisticESIM.getSubscriptionId());
+ mSubscriptionManager.addSubscriptionsIntoGroup(subList, groupUuid);
+ }
+
if (!opportunisticESIM.isOpportunistic()) {
Log.d(TAG, "set Opportunistic to TRUE");
mSubscriptionManager.setOpportunistic(true,
@@ -151,7 +156,7 @@ public class ONSProfileConfigurator {
PendingIntent callbackIntent = PendingIntent.getBroadcast(mContext,
REQUEST_CODE_ACTIVATE_SUB, intent, PendingIntent.FLAG_IMMUTABLE);
Log.d(TAG, "Activate oppSub request sent to SubManager");
- mSubscriptionManager.switchToSubscription(subId, callbackIntent);
+ mEuiccManager.switchToSubscription(subId, callbackIntent);
}
/**
@@ -253,6 +258,10 @@ public class ONSProfileConfigurator {
//Get the list of active subscriptions
List<SubscriptionInfo> availSubInfoList = mSubscriptionManager
.getAvailableSubscriptionInfoList();
+ if (availSubInfoList == null) {
+ Log.e(TAG, "getAvailableSubscriptionInfoList returned null");
+ return null;
+ }
Log.d(TAG, "Available subscriptions: " + availSubInfoList.size());
//Get the list of opportunistic carrier-ids list from carrier config.
@@ -264,8 +273,12 @@ public class ONSProfileConfigurator {
return null;
}
- ParcelUuid pSIMSubGroupId = mSubscriptionManager.getActiveSubscriptionInfo(pSIMId)
- .getGroupUuid();
+ SubscriptionInfo subscriptionInfo = mSubscriptionManager.getActiveSubscriptionInfo(pSIMId);
+ if (subscriptionInfo == null) {
+ Log.e(TAG, "getActiveSubscriptionInfo returned null for: " + pSIMId);
+ return null;
+ }
+ ParcelUuid pSIMSubGroupId = subscriptionInfo.getGroupUuid();
for (SubscriptionInfo subInfo : availSubInfoList) {
if (subInfo.getSubscriptionId() != pSIMId) {
for (int carrId : oppCarrierIdArr) {
diff --git a/src/com/android/ons/ONSProfileDownloader.java b/src/com/android/ons/ONSProfileDownloader.java
index f83aab9..11c6237 100644
--- a/src/com/android/ons/ONSProfileDownloader.java
+++ b/src/com/android/ons/ONSProfileDownloader.java
@@ -37,7 +37,7 @@ public class ONSProfileDownloader {
interface IONSProfileDownloaderListener {
void onDownloadComplete(int primarySubId);
- void onDownloadError(DownloadRetryOperationCode operationCode, int pSIMSubId);
+ void onDownloadError(int pSIMSubId, DownloadRetryResultCode resultCode, int detailErrCode);
}
private static final String TAG = ONSProfileDownloader.class.getName();
@@ -54,14 +54,16 @@ public class ONSProfileDownloader {
private final ONSProfileConfigurator mONSProfileConfig;
private IONSProfileDownloaderListener mListener;
- @VisibleForTesting
- protected enum DownloadRetryOperationCode{
+ // Subscription Id of the CBRS PSIM for which opportunistic eSIM is being downloaded. Used to
+ // ignore duplicate download requests when download is in progress.
+ private int mDownloadingPSimSubId;
+
+ protected enum DownloadRetryResultCode {
DOWNLOAD_SUCCESSFUL,
ERR_UNRESOLVABLE,
ERR_MEMORY_FULL,
ERR_INSTALL_ESIM_PROFILE_FAILED,
- ERR_RETRY_DOWNLOAD,
- BACKOFF_TIMER_EXPIRED
+ ERR_RETRY_DOWNLOAD
};
public ONSProfileDownloader(Context context, CarrierConfigManager carrierConfigManager,
@@ -85,8 +87,16 @@ public class ONSProfileDownloader {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case REQUEST_CODE_DOWNLOAD_SUB: { //arg1 -> ResultCode
+ // Received Response for download request. REQUEST_CODE_DOWNLOAD_SUB was sent to LPA
+ // as part of request intent.
+ case REQUEST_CODE_DOWNLOAD_SUB: {
Log.d(TAG, "REQUEST_CODE_DOWNLOAD_SUB callback received");
+
+ //Clear downloading subscription flag. Indicates no download in progress.
+ synchronized (this) {
+ mDownloadingPSimSubId = -1;
+ }
+
int pSIMSubId = ((Intent) msg.obj).getIntExtra(PARAM_PRIMARY_SUBID, 0);
int detailedErrCode = ((Intent) msg.obj).getIntExtra(
EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0);
@@ -99,23 +109,23 @@ public class ONSProfileDownloader {
Log.d(TAG, "Operation Code : " + operationCode);
Log.d(TAG, "Error Code : " + errorCode);
- DownloadRetryOperationCode opCode = mapDownloaderErrorCode(msg.arg1,
+ DownloadRetryResultCode resultCode = mapDownloaderErrorCode(msg.arg1,
detailedErrCode, operationCode, errorCode);
- Log.d(TAG, "DownloadRetryOperationCode: " + opCode);
+ Log.d(TAG, "DownloadRetryResultCode: " + resultCode);
- switch (opCode) {
+ switch (resultCode) {
case DOWNLOAD_SUCCESSFUL:
mListener.onDownloadComplete(pSIMSubId);
break;
case ERR_UNRESOLVABLE:
- mListener.onDownloadError(opCode, pSIMSubId);
+ mListener.onDownloadError(pSIMSubId, resultCode, detailedErrCode);
Log.e(TAG, "Unresolvable download error: "
+ getUnresolvableErrorDescription(errorCode));
break;
default:
- mListener.onDownloadError(opCode, pSIMSubId);
+ mListener.onDownloadError(pSIMSubId, resultCode, detailedErrCode);
break;
}
}
@@ -124,7 +134,7 @@ public class ONSProfileDownloader {
}
@VisibleForTesting
- protected DownloadRetryOperationCode mapDownloaderErrorCode(int resultCode,
+ protected DownloadRetryResultCode mapDownloaderErrorCode(int resultCode,
int detailedErrCode,
int operationCode,
int errorCode) {
@@ -138,17 +148,17 @@ public class ONSProfileDownloader {
//8.1 - eUICC, 4.8 - Insufficient Memory
// eUICC does not have sufficient space for this Profile.
if (errCode.equals(Pair.create("8.1.0", "4.8"))) {
- return DownloadRetryOperationCode.ERR_MEMORY_FULL;
+ return DownloadRetryResultCode.ERR_MEMORY_FULL;
}
//8.8.5 - Download order, 4.10 - Time to Live Expired
//The Download order has expired
if (errCode.equals(Pair.create("8.8.5", "4.10"))) {
- return DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD;
+ return DownloadRetryResultCode.ERR_RETRY_DOWNLOAD;
}
//All other errors are unresolvable or retry after SIM State Change
- return DownloadRetryOperationCode.ERR_UNRESOLVABLE;
+ return DownloadRetryResultCode.ERR_UNRESOLVABLE;
}
@@ -156,29 +166,29 @@ public class ONSProfileDownloader {
//Success Cases
case EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK: {
- return DownloadRetryOperationCode.DOWNLOAD_SUCCESSFUL;
+ return DownloadRetryResultCode.DOWNLOAD_SUCCESSFUL;
}
//Low eUICC memory cases
case EuiccManager.ERROR_EUICC_INSUFFICIENT_MEMORY: {
Log.d(TAG, "Download ERR: EUICC_INSUFFICIENT_MEMORY");
- return DownloadRetryOperationCode.ERR_MEMORY_FULL;
+ return DownloadRetryResultCode.ERR_MEMORY_FULL;
}
//Temporary download error cases
case EuiccManager.ERROR_TIME_OUT:
case EuiccManager.ERROR_CONNECTION_ERROR:
case EuiccManager.ERROR_OPERATION_BUSY: {
- return DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD;
+ return DownloadRetryResultCode.ERR_RETRY_DOWNLOAD;
}
//Profile installation failure cases
case EuiccManager.ERROR_INSTALL_PROFILE: {
- return DownloadRetryOperationCode.ERR_INSTALL_ESIM_PROFILE_FAILED;
+ return DownloadRetryResultCode.ERR_INSTALL_ESIM_PROFILE_FAILED;
}
default: {
- return DownloadRetryOperationCode.ERR_UNRESOLVABLE;
+ return DownloadRetryResultCode.ERR_UNRESOLVABLE;
}
}
}
@@ -214,14 +224,28 @@ public class ONSProfileDownloader {
return "Unknown";
}
- @VisibleForTesting
- protected void downloadProfile(int primarySubId) {
+ protected enum DownloadProfileResult {
+ SUCCESS,
+ DUPLICATE_REQUEST,
+ INVALID_SMDP_ADDRESS
+ }
+
+ protected DownloadProfileResult downloadProfile(int primarySubId) {
Log.d(TAG, "downloadProfile");
//Get SMDP address from carrier configuration.
String smdpAddress = getSMDPServerAddress(primarySubId);
if (smdpAddress == null || smdpAddress.length() <= 0) {
- return;
+ return DownloadProfileResult.INVALID_SMDP_ADDRESS;
+ }
+
+ synchronized (this) {
+ if (mDownloadingPSimSubId == primarySubId) {
+ Log.d(TAG, "Download already in progress.");
+ return DownloadProfileResult.DUPLICATE_REQUEST;
+ }
+
+ mDownloadingPSimSubId = primarySubId;
}
//Generate Activation code 1${SM-DP+ FQDN}$
@@ -236,6 +260,8 @@ public class ONSProfileDownloader {
Log.d(TAG, "Download Request sent to EUICC Manager");
mEuiccManager.downloadSubscription(DownloadableSubscription.forActivationCode(
activationCode), true, callbackIntent);
+
+ return DownloadProfileResult.SUCCESS;
}
/**
diff --git a/src/com/android/ons/ONSProfileSelector.java b/src/com/android/ons/ONSProfileSelector.java
index ab9168d..95287fc 100644
--- a/src/com/android/ons/ONSProfileSelector.java
+++ b/src/com/android/ons/ONSProfileSelector.java
@@ -31,10 +31,10 @@ import android.os.RemoteException;
import android.telephony.AvailableNetworkInfo;
import android.telephony.CellInfo;
import android.telephony.CellInfoLte;
+import android.telephony.CellInfoNr;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import android.telephony.UiccPortInfo;
@@ -43,7 +43,6 @@ import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ISetOpportunisticDataCallback;
-import com.android.internal.telephony.ISub;
import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
import com.android.telephony.Rlog;
@@ -195,7 +194,7 @@ public class ONSProfileSelector {
}
} else {
logDebug("switch to sub:" + subId);
- switchToSubscription(subId);
+ switchToSubscription(subId, getAvailableESIMPortIndex());
}
}
};
@@ -267,20 +266,28 @@ public class ONSProfileSelector {
}
}
- private String getMcc(CellInfo cellInfo) {
+ @VisibleForTesting
+ protected String getMcc(CellInfo cellInfo) {
String mcc = "";
if (cellInfo instanceof CellInfoLte) {
mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMccString();
}
+ else if (cellInfo instanceof CellInfoNr) {
+ mcc = ((CellInfoNr) cellInfo).getCellIdentity().getMccString();
+ }
return mcc;
}
- private String getMnc(CellInfo cellInfo) {
+ @VisibleForTesting
+ protected String getMnc(CellInfo cellInfo) {
String mnc = "";
if (cellInfo instanceof CellInfoLte) {
mnc = ((CellInfoLte) cellInfo).getCellIdentity().getMncString();
}
+ else if (cellInfo instanceof CellInfoNr) {
+ mnc = ((CellInfoNr) cellInfo).getCellIdentity().getMncString();
+ }
return mnc;
}
@@ -350,7 +357,7 @@ public class ONSProfileSelector {
private HashMap<Integer, IUpdateAvailableNetworksCallback> callbackStubs = new HashMap<>();
- private void switchToSubscription(int subId) {
+ private void switchToSubscription(int subId, int availableSIMPortIndex) {
Intent callbackIntent = new Intent(ACTION_SUB_SWITCH);
callbackIntent.setClass(mContext, OpportunisticNetworkService.class);
updateToken();
@@ -359,21 +366,22 @@ public class ONSProfileSelector {
mSubId = subId;
PendingIntent replyIntent = PendingIntent.getService(mContext,
1, callbackIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
- int eSIMPortIndex = getAvailableESIMPortIndex();
- if (eSIMPortIndex == TelephonyManager.INVALID_PORT_INDEX) {
+ if (availableSIMPortIndex == TelephonyManager.INVALID_PORT_INDEX) {
sendUpdateNetworksCallbackHelper(mNetworkScanCallback,
TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SIM_PORT_NOT_AVAILABLE);
return;
}
- mEuiccManager.switchToSubscription(subId, eSIMPortIndex, replyIntent);
+ mEuiccManager.switchToSubscription(subId, availableSIMPortIndex, replyIntent);
}
- private int getAvailableESIMPortIndex() {
- //Check if an opportunistic subscription is already active. If yes then, use the same port.
+ @VisibleForTesting
+ protected int getAvailableESIMPortIndex() {
//Check if an opportunistic subscription is already active. If yes then, use the same port.
List<SubscriptionInfo> subscriptionInfos = mSubscriptionManager
- .getActiveSubscriptionInfoList();
+ .getCompleteActiveSubscriptionInfoList();
if (subscriptionInfos != null) {
+ logDebug("[getAvailableESIMPortIndex] subscriptionInfos size:"
+ + subscriptionInfos.size());
for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
if (subscriptionInfo.isEmbedded() && subscriptionInfo.isOpportunistic()) {
return subscriptionInfo.getPortIndex();
@@ -383,12 +391,14 @@ public class ONSProfileSelector {
//Look for available port.
for (UiccCardInfo uiccCardInfo : mTelephonyManager.getUiccCardsInfo()) {
+ logDebug("[getAvailableESIMPortIndex] CardInfo: " + uiccCardInfo.toString());
if (!uiccCardInfo.isEuicc()) {
continue;
}
EuiccManager euiccManager = mEuiccManager.createForCardId(uiccCardInfo.getCardId());
for (UiccPortInfo uiccPortInfo : uiccCardInfo.getPorts()) {
+ logDebug("[getAvailableESIMPortIndex] PortInfo: " + uiccPortInfo.toString());
//Port is available if no profiles enabled on it.
if (euiccManager.isSimPortAvailable(uiccPortInfo.getPortIndex())) {
return uiccPortInfo.getPortIndex();
@@ -396,6 +406,7 @@ public class ONSProfileSelector {
}
}
+ logDebug("[getAvailableESIMPortIndex] No Port is available.");
return TelephonyManager.INVALID_PORT_INDEX;
}
@@ -481,31 +492,6 @@ public class ONSProfileSelector {
return new HashSet<>(availableNetworks1).equals(new HashSet<>(availableNetworks2));
}
- private boolean isPrimaryActiveOnOpportunisticSlot(
- ArrayList<AvailableNetworkInfo> availableNetworks) {
- /* Check if any of the available network is an embedded profile. if none are embedded,
- * return false
- * Todo <b/130535071> */
- if (!isOpportunisticSubEmbedded(availableNetworks)) {
- return false;
- }
-
- List<SubscriptionInfo> subscriptionInfos =
- mSubscriptionManager.getActiveSubscriptionInfoList(false);
- if (subscriptionInfos == null) {
- return false;
- }
-
- /* if there is a primary subscription active on the eSIM, return true */
- for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
- if (!subscriptionInfo.isOpportunistic() && subscriptionInfo.isEmbedded()) {
- return true;
- }
- }
-
- return false;
-
- }
private void sendUpdateNetworksCallbackHelper(IUpdateAvailableNetworksCallback callback,
int result) {
if (callback == null) {
@@ -537,11 +523,12 @@ public class ONSProfileSelector {
return;
}
- /* if primary subscription is active on opportunistic slot, do not switch out the same. */
- if (isPrimaryActiveOnOpportunisticSlot(availableNetworks)) {
- logDebug("primary subscription active on opportunistic sub");
+ /* Check if ports are available on the embedded slot */
+ int availSIMPortIndex = getAvailableESIMPortIndex();
+ if (availSIMPortIndex == TelephonyManager.INVALID_PORT_INDEX) {
+ logDebug("SIM port not available.");
sendUpdateNetworksCallbackHelper(callbackStub,
- TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
+ TelephonyManager.UPDATE_AVAILABLE_NETWORKS_SIM_PORT_NOT_AVAILABLE);
return;
}
@@ -574,7 +561,8 @@ public class ONSProfileSelector {
/* if subscription is not active, activate the sub */
if (!mSubscriptionManager.isActiveSubId(filteredAvailableNetworks.get(0).getSubId())) {
mNetworkScanCallback = callbackStub;
- switchToSubscription(filteredAvailableNetworks.get(0).getSubId());
+ switchToSubscription(filteredAvailableNetworks.get(0).getSubId(),
+ availSIMPortIndex);
} else {
if (enableModem(filteredAvailableNetworks.get(0).getSubId(), true)) {
sendUpdateNetworksCallbackHelper(callbackStub,
@@ -844,27 +832,12 @@ public class ONSProfileSelector {
ISetOpportunisticDataCallback callbackStub) {
if ((subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
|| (isOpprotunisticSub(subId) && mSubscriptionManager.isActiveSubId(subId))) {
- ISub iSub = ISub.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSubscriptionServiceRegisterer()
- .get());
- if (iSub == null) {
- log("Could not get Subscription Service handle");
- if (Compatibility.isChangeEnabled(
- OpportunisticNetworkService.CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
- sendSetOpptCallbackHelper(callbackStub,
- TelephonyManager.SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION);
- } else {
- sendSetOpptCallbackHelper(callbackStub,
- TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
- }
- return;
- }
try {
- iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub);
- } catch (RemoteException ex) {
- log("Could not connect to Subscription Service");
+ mSubscriptionManager.setPreferredDataSubscriptionId(subId, needValidation,
+ mHandler::post, result -> sendSetOpptCallbackHelper(callbackStub, result));
+ } catch (Exception ex) {
+ log("setPreferredDataSubscriptionId failed. subId=" + subId + ", needValidation="
+ + needValidation + ", ex=" + ex);
if (Compatibility.isChangeEnabled(
OpportunisticNetworkService.CALLBACK_ON_MORE_ERROR_CODE_CHANGE)) {
sendSetOpptCallbackHelper(callbackStub,
diff --git a/src/com/android/ons/ONSStats.java b/src/com/android/ons/ONSStats.java
new file mode 100644
index 0000000..d961344
--- /dev/null
+++ b/src/com/android/ons/ONSStats.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 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.ons;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import com.android.ons.ONSProfileActivator.Result;
+import com.android.ons.ONSProfileDownloader.DownloadRetryResultCode;
+
+import java.util.List;
+
+public class ONSStats {
+ private static final String ONS_ATOM_LOG_FILE = "ons_atom_log_info";
+ private static final String KEY_PROVISIONING_RESULT = "_provisioning_result";
+ private static final String KEY_DOWNLOAD_RESULT = "_download_result";
+ private static final String KEY_RETRY_COUNT = "_retry_count";
+ private static final String KEY_DETAILED_ERROR_CODE = "_detailed_error_code";
+ private static final String KEY_OPP_CARRIER_ID = "_opportunistic_carrier_id";
+ private static final String KEY_PRIMARY_CARRIER_ID = "_primary_sim_carrier_id";
+ private final Context mContext;
+ private final SubscriptionManager mSubscriptionManager;
+
+ /** Constructor to create instance for ONSStats. */
+ public ONSStats(Context context, SubscriptionManager subscriptionManager) {
+ mContext = context;
+ mSubscriptionManager = subscriptionManager;
+ }
+
+ /**
+ * It logs the ONS atom with the info passed as ONSStatsInfo. If the information is already
+ * logged, it will be skipped.
+ *
+ * @param info information to be logged.
+ * @return returns true if information is logged, otherwise false.
+ */
+ public boolean logEvent(ONSStatsInfo info) {
+ // check if the info needs to be ignored.
+ if (ignoreEvent(info)) {
+ return false;
+ }
+ int statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_UNKNOWN;
+ if (info.isProvisioningResultUpdated()) {
+ switch (info.getProvisioningResult()) {
+ case SUCCESS:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_SUCCESS;
+ break;
+ case ERR_CANNOT_SWITCH_TO_DUAL_SIM_MODE:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_SWITCH_TO_MULTISIM_FAILED;
+ break;
+ case ERR_CARRIER_DOESNT_SUPPORT_CBRS:
+ case ERR_AUTO_PROVISIONING_DISABLED:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_AUTO_PROVISIONING_DISABLED;
+ break;
+ case ERR_ESIM_NOT_SUPPORTED:
+ case ERR_MULTISIM_NOT_SUPPORTED:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_DEVICE_NOT_CAPABLE;
+ break;
+ case ERR_SINGLE_ACTIVE_OPPORTUNISTIC_SIM:
+ case ERR_DUAL_ACTIVE_SUBSCRIPTIONS:
+ case ERR_PSIM_NOT_FOUND:
+ case ERR_DOWNLOADED_ESIM_NOT_FOUND:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_ESIM_PROVISIONING_FAILED;
+ break;
+ case ERR_WAITING_FOR_INTERNET_CONNECTION:
+ case ERR_WAITING_FOR_WIFI_CONNECTION:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_INTERNET_NOT_AVAILABLE;
+ break;
+ case ERR_INVALID_CARRIER_CONFIG:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_UNRESOLVABLE_ERROR;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (info.getDownloadResult()) {
+ case ERR_UNRESOLVABLE:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_UNRESOLVABLE_ERROR;
+ break;
+ case ERR_MEMORY_FULL:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_MEMORY_FULL;
+ break;
+ case ERR_INSTALL_ESIM_PROFILE_FAILED:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_INSTALL_ESIM_PROFILE_FAILED;
+ break;
+ case ERR_RETRY_DOWNLOAD:
+ statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_CONNECTION_ERROR;
+ break;
+ default:
+ break;
+ }
+ }
+ OnsStatsLog.write(
+ OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE,
+ getSimCarrierId(info.getPrimarySimSubId()),
+ info.getOppSimCarrierId(),
+ info.isWifiConnected(),
+ statsCode,
+ info.getRetryCount(),
+ info.getDetailedErrCode());
+ updateSharedPreferences(info);
+ return true;
+ }
+
+ private void updateSharedPreferences(ONSStatsInfo info) {
+ SharedPreferences sharedPref =
+ mContext.getSharedPreferences(ONS_ATOM_LOG_FILE, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ if (info.isProvisioningResultUpdated()) {
+ editor.putInt(KEY_PROVISIONING_RESULT, info.getProvisioningResult().ordinal());
+ editor.remove(KEY_DOWNLOAD_RESULT);
+ } else {
+ editor.putInt(KEY_DOWNLOAD_RESULT, info.getDownloadResult().ordinal());
+ editor.remove(KEY_PROVISIONING_RESULT);
+ }
+ editor.putInt(KEY_PRIMARY_CARRIER_ID, getSimCarrierId(info.getPrimarySimSubId()))
+ .putInt(KEY_RETRY_COUNT, info.getRetryCount())
+ .putInt(KEY_OPP_CARRIER_ID, info.getOppSimCarrierId())
+ .putInt(KEY_DETAILED_ERROR_CODE, info.getDetailedErrCode())
+ .apply();
+ }
+
+ private boolean ignoreEvent(ONSStatsInfo info) {
+ Result result = info.getProvisioningResult();
+ if (info.isProvisioningResultUpdated()) {
+ info.setDetailedErrCode(result.ordinal());
+ // Codes are ignored since they are intermediate state of CBRS provisioning check.
+ if ((result == Result.DOWNLOAD_REQUESTED)
+ || result == Result.ERR_NO_SIM_INSERTED
+ || result == Result.ERR_DUPLICATE_DOWNLOAD_REQUEST
+ || result == Result.ERR_SWITCHING_TO_DUAL_SIM_MODE) {
+ return true;
+ }
+
+ // add subscription id for carrier if it doesn't support CBRS.
+ if (result == Result.ERR_CARRIER_DOESNT_SUPPORT_CBRS) {
+ List<SubscriptionInfo> subInfos =
+ mSubscriptionManager.getActiveSubscriptionInfoList();
+ info.setPrimarySimSubId(
+ (subInfos != null && !subInfos.isEmpty())
+ ? subInfos.get(0).getSubscriptionId()
+ : -1);
+ }
+ }
+
+ SharedPreferences sharedPref =
+ mContext.getSharedPreferences(ONS_ATOM_LOG_FILE, Context.MODE_PRIVATE);
+
+ boolean errorCodeUpdated =
+ (info.isProvisioningResultUpdated()
+ ? sharedPref.getInt(KEY_PROVISIONING_RESULT, -1) != result.ordinal()
+ : sharedPref.getInt(KEY_DOWNLOAD_RESULT, -1)
+ != info.getDownloadResult().ordinal());
+ boolean carrierIdUpdated =
+ sharedPref.getInt(KEY_PRIMARY_CARRIER_ID, -1)
+ != getSimCarrierId(info.getPrimarySimSubId());
+ boolean retryCountUpdated = sharedPref.getInt(KEY_RETRY_COUNT, -1) != info.getRetryCount();
+ boolean oppCarrierIdChanged =
+ sharedPref.getInt(KEY_OPP_CARRIER_ID, -1) != info.getOppSimCarrierId();
+ boolean detailedErrorChanged =
+ sharedPref.getInt(KEY_DETAILED_ERROR_CODE, -1) != info.getDetailedErrCode();
+ if (!(errorCodeUpdated
+ || carrierIdUpdated
+ || retryCountUpdated
+ || oppCarrierIdChanged
+ || detailedErrorChanged)) {
+ // Result codes are meant to log on every occurrence. These should not be ignored.
+ if (result == Result.SUCCESS
+ || result == Result.ERR_DOWNLOADED_ESIM_NOT_FOUND
+ || info.getDownloadResult()
+ == DownloadRetryResultCode.ERR_INSTALL_ESIM_PROFILE_FAILED) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private int getSimCarrierId(int subId) {
+ if (subId == -1) return -1;
+ SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId);
+ return (subInfo != null) ? subInfo.getCarrierId() : -1;
+ }
+}
diff --git a/src/com/android/ons/ONSStatsInfo.java b/src/com/android/ons/ONSStatsInfo.java
new file mode 100644
index 0000000..080ed4a
--- /dev/null
+++ b/src/com/android/ons/ONSStatsInfo.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2022 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.ons;
+
+import com.android.ons.ONSProfileActivator.Result;
+import com.android.ons.ONSProfileDownloader.DownloadRetryResultCode;
+
+public final class ONSStatsInfo {
+ public static final int INVALID_VALUE = -1;
+ private Result mProvisioningResult = null;
+ private DownloadRetryResultCode mDownloadResult = null;
+ private int mPrimarySimSubId = INVALID_VALUE;
+ private int mOppSimCarrierId = INVALID_VALUE;
+ private int mRetryCount = INVALID_VALUE;
+ private int mDetailedErrCode = INVALID_VALUE;
+ private boolean mIsWifiConnected = false;
+ private boolean mIsProvisioningResultUpdated = false;
+
+ public Result getProvisioningResult() {
+ return mProvisioningResult;
+ }
+
+ public DownloadRetryResultCode getDownloadResult() {
+ return mDownloadResult;
+ }
+
+ public int getPrimarySimSubId() {
+ return mPrimarySimSubId;
+ }
+
+ public int getOppSimCarrierId() {
+ return mOppSimCarrierId;
+ }
+
+ public int getRetryCount() {
+ return mRetryCount;
+ }
+
+ public int getDetailedErrCode() {
+ return mDetailedErrCode;
+ }
+
+ public boolean isWifiConnected() {
+ return mIsWifiConnected;
+ }
+
+ public boolean isProvisioningResultUpdated() {
+ return mIsProvisioningResultUpdated;
+ }
+
+ public ONSStatsInfo setProvisioningResult(Result result) {
+ mProvisioningResult = result;
+ mDownloadResult = null;
+ mIsProvisioningResultUpdated = true;
+ return this;
+ }
+
+ public ONSStatsInfo setDownloadResult(DownloadRetryResultCode retryResultCode) {
+ mProvisioningResult = null;
+ mDownloadResult = retryResultCode;
+ mIsProvisioningResultUpdated = false;
+ return this;
+ }
+
+ public ONSStatsInfo setPrimarySimSubId(int primarySimSubId) {
+ mPrimarySimSubId = primarySimSubId;
+ return this;
+ }
+
+ public ONSStatsInfo setOppSimCarrierId(int oppSimCarrierId) {
+ mOppSimCarrierId = oppSimCarrierId;
+ return this;
+ }
+
+ public ONSStatsInfo setRetryCount(int retryCount) {
+ mRetryCount = retryCount;
+ return this;
+ }
+
+ public ONSStatsInfo setDetailedErrCode(int detailedErrCode) {
+ mDetailedErrCode = detailedErrCode;
+ return this;
+ }
+
+ public ONSStatsInfo setWifiConnected(boolean wifiConnected) {
+ mIsWifiConnected = wifiConnected;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "ONSStatsInfo{"
+ + "mProvisioningResult="
+ + mProvisioningResult
+ + ", mDownloadResult="
+ + mDownloadResult
+ + ", mPrimarySimSubId="
+ + mPrimarySimSubId
+ + ", mOppSimCarrierId="
+ + mOppSimCarrierId
+ + ", mRetryCount="
+ + mRetryCount
+ + ", mDetailedErrCode="
+ + mDetailedErrCode
+ + ", mIsWifiConnected="
+ + mIsWifiConnected
+ + ", mIsProvisioningResultUpdated="
+ + mIsProvisioningResultUpdated
+ + '}';
+ }
+}
diff --git a/src/com/android/ons/OpportunisticNetworkService.java b/src/com/android/ons/OpportunisticNetworkService.java
index 13e7034..d41051c 100644
--- a/src/com/android/ons/OpportunisticNetworkService.java
+++ b/src/com/android/ons/OpportunisticNetworkService.java
@@ -35,6 +35,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.TelephonyServiceManager.ServiceRegisterer;
import android.telephony.AvailableNetworkInfo;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
@@ -62,6 +63,7 @@ public class OpportunisticNetworkService extends Service {
private TelephonyManager mTelephonyManager;
@VisibleForTesting protected SubscriptionManager mSubscriptionManager;
private ONSProfileActivator mONSProfileActivator;
+ private ONSStats mONSStats;
private Handler mHandler = null;
private final Object mLock = new Object();
@@ -311,10 +313,19 @@ public class OpportunisticNetworkService extends Service {
@Override
public int getPreferredDataSubscriptionId(String callingPackage,
String callingFeatureId) {
- TelephonyPermissions
- .checkCallingOrSelfReadPhoneState(mContext,
- mSubscriptionManager.getDefaultSubscriptionId(),
- callingPackage, callingFeatureId, "getPreferredDataSubscriptionId");
+ if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(
+ mContext,
+ Binder.getCallingPid(),
+ Binder.getCallingUid(),
+ callingPackage,
+ callingFeatureId,
+ "getPreferredDataSubscriptionId")) {
+ throw new SecurityException(
+ "getPreferredDataSubscriptionId requires READ_PHONE_STATE,"
+ + " READ_PRIVILEGED_PHONE_STATE, or carrier privileges on"
+ + " any active subscription.");
+ }
+
final long identity = Binder.clearCallingIdentity();
try {
return mProfileSelector.getPreferredDataSubscriptionId();
@@ -421,7 +432,7 @@ public class OpportunisticNetworkService extends Service {
}
break;
- case ONSProfileActivator.ACTION_CARRIER_CONFIG_CHANGED:
+ case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
mONSProfileActivator.handleCarrierConfigChange();
break;
}
@@ -455,10 +466,11 @@ public class OpportunisticNetworkService extends Service {
mSubscriptionManager = (SubscriptionManager) mContext.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
mONSConfigInputHashMap = new HashMap<String, ONSConfigInput>();
+ mONSStats = new ONSStats(mContext, mSubscriptionManager);
mContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED));
enableOpportunisticNetwork(getPersistentEnableState());
- mONSProfileActivator = new ONSProfileActivator(mContext);
+ mONSProfileActivator = new ONSProfileActivator(mContext, mONSStats);
}
private void handleCarrierAppAvailableNetworks(
diff --git a/tests/src/com/android/ons/ONSNetworkScanCtlrTest.java b/tests/src/com/android/ons/ONSNetworkScanCtlrTest.java
index e4470c5..0053adc 100644
--- a/tests/src/com/android/ons/ONSNetworkScanCtlrTest.java
+++ b/tests/src/com/android/ons/ONSNetworkScanCtlrTest.java
@@ -20,31 +20,25 @@ import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.*;
import android.os.Looper;
-import android.os.PersistableBundle;
import android.telephony.AccessNetworkConstants;
import android.telephony.AvailableNetworkInfo;
-import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityNr;
import android.telephony.CellInfo;
import android.telephony.CellInfoLte;
+import android.telephony.CellInfoNr;
import android.telephony.NetworkScan;
import android.telephony.NetworkScanRequest;
import android.telephony.RadioAccessSpecifier;
import android.telephony.SubscriptionInfo;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import java.sql.Array;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
public class ONSNetworkScanCtlrTest extends ONSBaseTest {
@@ -341,4 +335,16 @@ public class ONSNetworkScanCtlrTest extends ONSBaseTest {
waitUntilReady();
mReady = false;
}
+
+ @Test
+ public void testGetMncMccFromCellInfoNr() {
+ mONSNetworkScanCtlr = new ONSNetworkScanCtlr(mContext, mMockTelephonyManager, null);
+
+ CellIdentityNr cellIdentityNr = new CellIdentityNr(0, 0, 0, new int[]{0}, "111", "222", 0,
+ "", "", Collections.emptyList());
+
+ CellInfoNr cellinfoNr = new CellInfoNr(0, true, 0, cellIdentityNr, null);
+
+ assertEquals(mONSNetworkScanCtlr.getMccMnc(cellinfoNr), "111222");
+ }
}
diff --git a/tests/src/com/android/ons/ONSProfileActivatorTest.java b/tests/src/com/android/ons/ONSProfileActivatorTest.java
index c678d24..478f23a 100644
--- a/tests/src/com/android/ons/ONSProfileActivatorTest.java
+++ b/tests/src/com/android/ons/ONSProfileActivatorTest.java
@@ -18,6 +18,8 @@ package com.android.ons;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.res.Resources;
@@ -25,6 +27,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Looper;
+import android.os.ParcelUuid;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
@@ -41,9 +44,12 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
public class ONSProfileActivatorTest extends ONSBaseTest {
private static final String TAG = ONSProfileActivatorTest.class.getName();
+ private static final int TEST_SUBID_0 = 0;
+ private static final int TEST_SUBID_1 = 1;
@Mock
Context mMockContext;
@@ -66,18 +72,20 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Mock
SubscriptionInfo mMockSubInfo;
@Mock
- SubscriptionInfo mMockSubInfo2;
+ SubscriptionInfo mMockSubInfo1;
@Mock
List<SubscriptionInfo> mMocksubsInPSIMGroup;
@Mock
Resources mMockResources;
+ @Mock
+ ONSStats mMockONSStats;
@Before
public void setUp() throws Exception {
super.setUp("ONSTest");
MockitoAnnotations.initMocks(this);
Looper.prepare();
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(mMockResources).when(mMockContext).getResources();
doReturn(mMockConnectivityManager).when(mMockContext).getSystemService(
@@ -86,6 +94,36 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
doNothing().when(mMockConnectivityManager).registerNetworkCallback(request,
new ConnectivityManager.NetworkCallback());
+
+ PersistableBundle persistableBundle = new PersistableBundle();
+ persistableBundle.putBoolean(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, true);
+ doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUBID_1);
+ }
+
+ // Worker thread is used for testing asynchronous APIs and Message Handlers.
+ // ASync APIs are called and Handler messages are processed by Worker thread. Test results are
+ // verified by Main Thread.
+ static class WorkerThread extends Thread {
+ Looper mWorkerLooper;
+ private final Runnable mRunnable;
+
+ WorkerThread(Runnable runnable) {
+ mRunnable = runnable;
+ }
+
+ @Override
+ public void run() {
+ super.run();
+ Looper.prepare();
+ mWorkerLooper = Looper.myLooper();
+ mRunnable.run();
+ mWorkerLooper.loop();
+ }
+
+ public void exit() {
+ mWorkerLooper.quitSafely();
+ }
}
/*@Test
@@ -102,12 +140,13 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
public void testONSAutoProvisioningDisabled() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(false).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_AUTO_PROVISIONING_DISABLED,
onsProfileActivator.handleCarrierConfigChange());
@@ -115,13 +154,14 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
public void testESIMNotSupported() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(false).when(mMockEuiccManager).isEnabled();
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_ESIM_NOT_SUPPORTED,
onsProfileActivator.handleCarrierConfigChange());
@@ -130,7 +170,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
//@DisplayName("Single SIM Device with eSIM support")
public void testMultiSIMNotSupported() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(1).when(mMockTeleManager).getSupportedModemCount();
@@ -138,7 +178,8 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_MULTISIM_NOT_SUPPORTED,
onsProfileActivator.handleCarrierConfigChange());
@@ -146,7 +187,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
public void testDeviceSwitchToDualSIMModeFailed() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(2).when(mMockTeleManager).getSupportedModemCount();
@@ -154,18 +195,14 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
doReturn(true).when(mMockTeleManager).doesSwitchMultiSimConfigTriggerReboot();
doReturn(mMockactiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
doReturn(1).when(mMockactiveSubInfos).size();
- doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(0);
+ doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(TEST_SUBID_0);
doReturn(1).when(mMockSubInfo).getSubscriptionId();
doReturn(false).when(mMockSubInfo).isOpportunistic();
- PersistableBundle persistableBundle = new PersistableBundle();
- persistableBundle.putBoolean(CarrierConfigManager
- .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, true);
- doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(1);
-
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_CANNOT_SWITCH_TO_DUAL_SIM_MODE,
onsProfileActivator.handleCarrierConfigChange());
@@ -173,26 +210,23 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
public void testDeviceSwitchToDualSIMModeSuccess() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(2).when(mMockTeleManager).getSupportedModemCount();
doReturn(1).when(mMockTeleManager).getActiveModemCount();
doReturn(mMockactiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
doReturn(1).when(mMockactiveSubInfos).size();
- doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(0);
+ doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(TEST_SUBID_0);
doReturn(1).when(mMockSubInfo).getSubscriptionId();
doReturn(false).when(mMockSubInfo).isOpportunistic();
- PersistableBundle persistableBundle = new PersistableBundle();
- persistableBundle.putBoolean(CarrierConfigManager
- .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, true);
- doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(1);
doReturn(false).when(mMockTeleManager).doesSwitchMultiSimConfigTriggerReboot();
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_SWITCHING_TO_DUAL_SIM_MODE,
onsProfileActivator.handleCarrierConfigChange());
@@ -200,7 +234,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
//@DisplayName("Dual SIM device with no SIM inserted")
public void testNoActiveSubscriptions() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(2).when(mMockTeleManager).getSupportedModemCount();
@@ -210,7 +244,25 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
+
+ assertEquals(ONSProfileActivator.Result.ERR_NO_SIM_INSERTED,
+ onsProfileActivator.handleCarrierConfigChange());
+ }
+
+ public void testNullActiveSubscriptionList() {
+
+ doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
+ doReturn(true).when(mMockEuiccManager).isEnabled();
+ doReturn(2).when(mMockTeleManager).getSupportedModemCount();
+ doReturn(2).when(mMockTeleManager).getActiveModemCount();
+ doReturn(null).when(mMockSubManager).getActiveSubscriptionInfoList();
+
+ ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
+ mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_NO_SIM_INSERTED,
onsProfileActivator.handleCarrierConfigChange());
@@ -219,7 +271,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
//@DisplayName("Dual SIM device and non CBRS carrier pSIM inserted")
public void testNonCBRSCarrierPSIMInserted() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(2).when(mMockTeleManager).getSupportedModemCount();
@@ -228,17 +280,18 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
PersistableBundle persistableBundle = new PersistableBundle();
persistableBundle.putBoolean(CarrierConfigManager
.KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false);
- doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(1);
+ doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUBID_0);
doReturn(mMockactiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
doReturn(1).when(mMockactiveSubInfos).size();
- doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(0);
- doReturn(1).when(mMockSubInfo).getSubscriptionId();
+ doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(TEST_SUBID_0);
+ doReturn(TEST_SUBID_0).when(mMockSubInfo).getSubscriptionId();
doReturn(false).when(mMockSubInfo).isOpportunistic();
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_CARRIER_DOESNT_SUPPORT_CBRS,
onsProfileActivator.handleCarrierConfigChange());
@@ -247,7 +300,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
//@DisplayName("Dual SIM device with Two PSIM active subscriptions")
public void testTwoActivePSIMSubscriptions() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(2).when(mMockTeleManager).getSupportedModemCount();
@@ -255,69 +308,101 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
ArrayList<SubscriptionInfo> mActiveSubInfos = new ArrayList<>();
mActiveSubInfos.add(mMockSubInfo);
- mActiveSubInfos.add(mMockSubInfo2);
+ mActiveSubInfos.add(mMockSubInfo1);
doReturn(mActiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
doReturn(false).when(mMockSubInfo).isEmbedded();
- doReturn(false).when(mMockSubInfo2).isEmbedded();
+ doReturn(false).when(mMockSubInfo1).isEmbedded();
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_DUAL_ACTIVE_SUBSCRIPTIONS,
onsProfileActivator.handleCarrierConfigChange());
}
- /*@Test
- //Cannot mock/spy class android.os.PersistableBundle
- public void testOneActivePSIMAndOneNonOpportunisticESIM() {
- doReturn(true).when(mMockONSUtil).isESIMSupported();
- doReturn(true).when(mMockONSUtil).isMultiSIMPhone();
+ @Test
+ public void testOneCBRSPSIMAndOneNonCBRSESIM() {
+ doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
+ doReturn(true).when(mMockEuiccManager).isEnabled();
+ doReturn(2).when(mMockTeleManager).getSupportedModemCount();
+ doReturn(2).when(mMockTeleManager).getActiveModemCount();
+
ArrayList<SubscriptionInfo> mActiveSubInfos = new ArrayList<>();
+ mActiveSubInfos.add(mMockSubInfo);
mActiveSubInfos.add(mMockSubInfo1);
- mActiveSubInfos.add(mMockSubInfo2);
doReturn(mActiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
- doReturn(false).when(mMockSubInfo1).isEmbedded();
- doReturn(true).when(mMockSubInfo2).isEmbedded();
- //0 - using carrier-id=0 to make sure it doesn't map to any opportunistic carrier-id
- doReturn(0).when(mMockSubInfo2).getCarrierId();
+ doReturn(false).when(mMockSubInfo).isEmbedded();
+ doReturn(true).when(mMockSubInfo1).isEmbedded();
+ doReturn(TEST_SUBID_0).when(mMockSubInfo).getSubscriptionId();
+ doReturn(TEST_SUBID_1).when(mMockSubInfo1).getSubscriptionId();
+
+ PersistableBundle persistableBundle = new PersistableBundle();
+ persistableBundle.putBoolean(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false);
+ doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUBID_0);
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
- mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_DUAL_ACTIVE_SUBSCRIPTIONS,
- onsProfileActivator.handleSimStateChange());
- }*/
+ onsProfileActivator.handleCarrierConfigChange());
+ }
+
+ @Test
+ public void testOneCBRSPSIMAndOneOpportunisticESIM() {
+ doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
+ doReturn(true).when(mMockEuiccManager).isEnabled();
+ doReturn(2).when(mMockTeleManager).getSupportedModemCount();
+ doReturn(2).when(mMockTeleManager).getActiveModemCount();
- /*@Test
- //Cannot mock/spy class android.os.PersistableBundle
- public void testOneActivePSIMAndOneOpportunisticESIM() {
- doReturn(true).when(mMockONSUtil).isESIMSupported();
- doReturn(true).when(mMockONSUtil).isMultiSIMPhone();
ArrayList<SubscriptionInfo> mActiveSubInfos = new ArrayList<>();
- mActiveSubInfos.add(mMockSubInfo1);
- mActiveSubInfos.add(mMockSubInfo2);
+ mActiveSubInfos.add(mMockSubInfo); //Primary CBRS SIM
+ mActiveSubInfos.add(mMockSubInfo1); //Opportunistic eSIM
doReturn(mActiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
- doReturn(false).when(mMockSubInfo1).isEmbedded();
- doReturn(true).when(mMockSubInfo2).isEmbedded();
- doReturn(1).when(mMockSubInfo2).getSubscriptionId();
- doReturn(mMockCarrierConfig).when(mMockCarrierConfigManager).getConfigForSubId(1);
- doReturn(new int[]{1}).when(mMockCarrierConfig).get(
- CarrierConfigManager.KEY_OPPORTUNISTIC_CARRIER_IDS_INT_ARRAY);
- //1 - using carrier-id=1 to match with opportunistic carrier-id
- doReturn(1).when(mMockSubInfo2).getCarrierId();
+ doReturn(mActiveSubInfos).when(mMockSubManager).getAvailableSubscriptionInfoList();
+
+ doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUBID_0);
+ doReturn(TEST_SUBID_0).when(mMockSubInfo).getSubscriptionId();
+ doReturn(true).when(mMockSubManager).isActiveSubscriptionId(TEST_SUBID_0);
+ doReturn(false).when(mMockSubInfo).isOpportunistic();
+ doReturn(false).when(mMockSubInfo).isEmbedded();
+ ParcelUuid pSIMSubGroupId = new ParcelUuid(new UUID(0, 1));
+ doReturn(pSIMSubGroupId).when(mMockSubInfo).getGroupUuid();
+ PersistableBundle persistableBundle = new PersistableBundle();
+ persistableBundle.putBoolean(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, true);
+ persistableBundle.putIntArray(CarrierConfigManager
+ .KEY_OPPORTUNISTIC_CARRIER_IDS_INT_ARRAY, new int[]{1, 2});
+ doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUBID_0);
+
+ doReturn(mMockSubInfo1).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUBID_1);
+ doReturn(TEST_SUBID_1).when(mMockSubInfo1).getSubscriptionId();
+ doReturn(true).when(mMockSubManager).isActiveSubscriptionId(TEST_SUBID_1);
+ doReturn(true).when(mMockSubInfo1).isOpportunistic();
+ doReturn(true).when(mMockSubInfo1).isEmbedded();
+ doReturn(pSIMSubGroupId).when(mMockSubInfo1).getGroupUuid();
+ doReturn(1).when(mMockSubInfo1).getCarrierId();
+
+ doReturn(mMockSubInfo1).when(mMockONSProfileConfigurator)
+ .findOpportunisticSubscription(TEST_SUBID_0);
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
- mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.SUCCESS,
- onsProfileActivator.handleSimStateChange());
- }*/
+ onsProfileActivator.handleCarrierConfigChange());
+ }
@Test
//@DisplayName("Dual SIM device with only opportunistic eSIM active")
public void testOnlyOpportunisticESIMActive() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(2).when(mMockTeleManager).getSupportedModemCount();
@@ -329,7 +414,8 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_SINGLE_ACTIVE_OPPORTUNISTIC_SIM,
onsProfileActivator.handleCarrierConfigChange());
@@ -338,30 +424,28 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
@Test
//@DisplayName("Dual SIM device, only CBRS carrier pSIM inserted and pSIM not Grouped")
public void testCBRSpSIMAndNotGrouped() {
- doReturn(TelephonyManager.SIM_STATE_READY).when(mMockTeleManager).getSimState();
+
doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
doReturn(true).when(mMockEuiccManager).isEnabled();
doReturn(2).when(mMockTeleManager).getSupportedModemCount();
doReturn(2).when(mMockTeleManager).getActiveModemCount();
- PersistableBundle persistableBundle = new PersistableBundle();
- persistableBundle.putBoolean(CarrierConfigManager
- .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, true);
- doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(1);
-
doReturn(mMockactiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
doReturn(1).when(mMockactiveSubInfos).size();
doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(0);
doReturn(false).when(mMockSubInfo).isOpportunistic();
- doReturn(1).when(mMockSubInfo).getSubscriptionId();
+ doReturn(TEST_SUBID_1).when(mMockSubInfo).getSubscriptionId();
doReturn(null).when(mMockSubInfo).getGroupUuid();
+ doReturn(ONSProfileDownloader.DownloadProfileResult.SUCCESS).when(mMockONSProfileDownloader)
+ .downloadProfile(TEST_SUBID_1);
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
mMockSubManager, mMockTeleManager, mMockCarrierConfigManager, mMockEuiccManager,
- mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockConnectivityManager, mMockONSProfileConfigurator, mMockONSProfileDownloader,
+ mMockONSStats);
onsProfileActivator.mIsInternetConnAvailable = true;
- assertEquals(ONSProfileActivator.Result.SUCCESS,
+ assertEquals(ONSProfileActivator.Result.DOWNLOAD_REQUESTED,
onsProfileActivator.handleCarrierConfigChange());
}
@@ -400,8 +484,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
}
};
- ONSProfileDownloaderTest.WorkerThread workerThread = new ONSProfileDownloaderTest
- .WorkerThread(runnable);
+ WorkerThread workerThread = new WorkerThread(runnable);
workerThread.start();
synchronized (lock) {
@@ -441,7 +524,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
ONSProfileActivator onsProfileActivator =
new ONSProfileActivator(mMockContext, mMockSubManager, mMockEuiCCManager,
mMockTeleManager,
- mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockONSProfileConfigurator, mMockONSProfileDownloader, mMockONSStats);
assertEquals(ONSProfileActivator.Result.SUCCESS,
onsProfileActivator.handleSimStateChange());
@@ -516,7 +599,7 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
//TODO: mock ParcelUuid - pSIM group
ONSProfileActivator onsProfileActivator = new ONSProfileActivator(mMockContext,
- mMockONSProfileConfigurator, mMockONSProfileDownloader);
+ mMockONSProfileConfigurator, mMockONSProfileDownloader, mMockONSStats);
assertEquals(ONSProfileActivator.Result.ERR_INVALID_PSIM_SUBID,
onsProfileActivator.retryDownloadAfterReboot());
@@ -537,8 +620,88 @@ public class ONSProfileActivatorTest extends ONSBaseTest {
verify(mMockEUICCManager, never()).downloadSubscription(null, true, null);
}*/
+ @Test
+ public void testESIMDownloadFailureAndRetry() {
+ doReturn(true).when(mMockResources).getBoolean(R.bool.enable_ons_auto_provisioning);
+ doReturn(true).when(mMockEuiccManager).isEnabled();
+ doReturn(2).when(mMockTeleManager).getSupportedModemCount();
+ doReturn(2).when(mMockTeleManager).getActiveModemCount();
+ doReturn(ONSProfileDownloader.DownloadProfileResult.SUCCESS).when(mMockONSProfileDownloader)
+ .downloadProfile(TEST_SUBID_0);
+
+ doReturn(mMockactiveSubInfos).when(mMockSubManager).getActiveSubscriptionInfoList();
+ doReturn(1).when(mMockactiveSubInfos).size();
+ doReturn(mMockSubInfo).when(mMockactiveSubInfos).get(0);
+ doReturn(false).when(mMockSubInfo).isOpportunistic();
+ doReturn(TEST_SUBID_0).when(mMockSubInfo).getSubscriptionId();
+ doReturn(null).when(mMockSubInfo).getGroupUuid();
+
+ final int maxRetryCount = 5;
+ final int retryBackoffTime = 1; //1 second
+
+ PersistableBundle persistableBundle = new PersistableBundle();
+ persistableBundle.putBoolean(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, true);
+ persistableBundle.putInt(CarrierConfigManager
+ .KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, maxRetryCount);
+ persistableBundle.putInt(CarrierConfigManager
+ .KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, retryBackoffTime);
+ doReturn(persistableBundle).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUBID_0);
+
+ final Object lock = new Object();
+ class TestRunnable implements Runnable {
+ public ONSProfileActivator mOnsProfileActivator;
+
+ @Override
+ public void run() {
+ mOnsProfileActivator = new ONSProfileActivator(mMockContext,
+ mMockSubManager, mMockTeleManager, mMockCarrierConfigManager,
+ mMockEuiccManager, mMockConnectivityManager, mMockONSProfileConfigurator,
+ mMockONSProfileDownloader, mMockONSStats);
+
+ synchronized (lock) {
+ lock.notify();
+ }
+ }
+ }
+
+ TestRunnable runnable = new TestRunnable();
+ WorkerThread workerThread = new WorkerThread(runnable);
+ workerThread.start();
+
+ synchronized (lock) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ ONSProfileActivator onsProfileActivator = runnable.mOnsProfileActivator;
+ onsProfileActivator.mIsInternetConnAvailable = true;
+
+ for (int idx = 0; idx <= maxRetryCount; idx++) {
+ onsProfileActivator.onDownloadError(
+ TEST_SUBID_0,
+ ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
+
+ //Wait for Handler to process download message. Backoff delay + 500 milli secs.
+ try {
+ Thread.sleep(onsProfileActivator.calculateBackoffDelay(
+ onsProfileActivator.mDownloadRetryCount, retryBackoffTime) + 1000);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ workerThread.exit();
+
+ verify(mMockONSProfileDownloader, times(maxRetryCount)).downloadProfile(TEST_SUBID_0);
+ }
+
@After
public void tearDown() throws Exception {
super.tearDown();
}
-} \ No newline at end of file
+}
+
diff --git a/tests/src/com/android/ons/ONSProfileConfiguratorTest.java b/tests/src/com/android/ons/ONSProfileConfiguratorTest.java
index 394a3ae..7c88658 100644
--- a/tests/src/com/android/ons/ONSProfileConfiguratorTest.java
+++ b/tests/src/com/android/ons/ONSProfileConfiguratorTest.java
@@ -97,6 +97,22 @@ public class ONSProfileConfiguratorTest extends ONSBaseTest {
}
@Test
+ public void testAlreadyGroupedSubscriptions() {
+ doReturn(TEST_SUB_ID).when(mMockSubscriptionInfo1).getSubscriptionId();
+ doReturn(true).when(mMockSubscriptionInfo1).isOpportunistic();
+
+ ONSProfileConfigurator mOnsProfileConfigurator = new ONSProfileConfigurator(mContext,
+ mMockSubManager, mMockCarrierConfigManager, mMockEuiccMngr, mMockConfigListener);
+
+ ParcelUuid uuid = new ParcelUuid(new UUID(1, 2));
+ doReturn(uuid).when(mMockSubscriptionInfo1).getGroupUuid();
+
+ mOnsProfileConfigurator.groupWithPSIMAndSetOpportunistic(mMockSubscriptionInfo1, uuid);
+
+ verifyNoMoreInteractions(mMockSubManager);
+ }
+
+ @Test
public void testActivateSubscription() {
ONSProfileConfigurator mOnsProfileConfigurator = new ONSProfileConfigurator(mContext,
mMockSubManager, mMockCarrierConfigManager, mMockEuiccMngr, mMockConfigListener);
@@ -115,7 +131,7 @@ public class ONSProfileConfiguratorTest extends ONSBaseTest {
PendingIntent.FLAG_IMMUTABLE);
mOnsProfileConfigurator.activateSubscription(TEST_SUB_ID);
- verify(mMockSubManager).switchToSubscription(TEST_SUB_ID, callbackIntent);
+ verify(mMockEuiccMngr).switchToSubscription(TEST_SUB_ID, callbackIntent);
}
@Test
diff --git a/tests/src/com/android/ons/ONSProfileDownloaderTest.java b/tests/src/com/android/ons/ONSProfileDownloaderTest.java
index f37ef1e..e82df6a 100644
--- a/tests/src/com/android/ons/ONSProfileDownloaderTest.java
+++ b/tests/src/com/android/ons/ONSProfileDownloaderTest.java
@@ -16,9 +16,12 @@
package com.android.ons;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -33,6 +36,8 @@ import android.telephony.euicc.EuiccManager;
import android.util.Log;
import android.util.Pair;
+import com.android.ons.ONSProfileDownloader.DownloadProfileResult;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -42,7 +47,7 @@ import org.mockito.MockitoAnnotations;
public class ONSProfileDownloaderTest extends ONSBaseTest {
private static final String TAG = ONSProfileDownloaderTest.class.getName();
private static final int TEST_SUB_ID = 1;
- private static final String TEST_SMDP_ADDRESS = "LPA:1$TEST-ESIM.COM$";
+ private static final String TEST_SMDP_ADDRESS = "TEST-ESIM.COM";
@Mock
Context mMockContext;
@@ -117,8 +122,9 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
@Override
public void onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode operationCode,
- int pSIMSubId) {
+ int pSIMSubId,
+ ONSProfileDownloader.DownloadRetryResultCode operationCode,
+ int detailedErrorCode) {
}
};
@@ -233,8 +239,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
}
verify(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_MEMORY_FULL,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_MEMORY_FULL, 0);
workerThread.exit();
}
@@ -246,8 +251,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
doNothing().when(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
Runnable runnable = new Runnable() {
@Override
@@ -288,8 +292,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
.getEncodedActivationCode();
verify(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
workerThread.exit();
}
@@ -302,8 +305,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
doNothing().when(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
Runnable runnable = new Runnable() {
@Override
@@ -344,8 +346,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
.getEncodedActivationCode();
verify(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
workerThread.exit();
}
@@ -358,8 +359,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
doNothing().when(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
Runnable runnable = new Runnable() {
@Override
@@ -400,8 +400,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
.getEncodedActivationCode();
verify(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
workerThread.exit();
}
@@ -414,8 +413,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
doNothing().when(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_RETRY_DOWNLOAD,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
Runnable runnable = new Runnable() {
@Override
@@ -450,8 +448,7 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
}
verify(mMockDownloadListener).onDownloadError(
- ONSProfileDownloader.DownloadRetryOperationCode.ERR_UNRESOLVABLE,
- TEST_SUB_ID);
+ TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_UNRESOLVABLE, 0);
workerThread.exit();
}
@@ -469,51 +466,51 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
ONSProfileDownloader.DownloadHandler downloadHandler =
onsProfileDownloader.new DownloadHandler();
- ONSProfileDownloader.DownloadRetryOperationCode res =
+ ONSProfileDownloader.DownloadRetryResultCode res =
downloadHandler.mapDownloaderErrorCode(
EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0, 0, 0);
assertEquals(
- ONSProfileDownloader.DownloadRetryOperationCode.DOWNLOAD_SUCCESSFUL, res);
+ ONSProfileDownloader.DownloadRetryResultCode.DOWNLOAD_SUCCESSFUL, res);
res = downloadHandler.mapDownloaderErrorCode(
EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
EuiccManager.OPERATION_EUICC_GSMA,
EuiccManager.ERROR_EUICC_INSUFFICIENT_MEMORY);
- assertEquals(ONSProfileDownloader.DownloadRetryOperationCode
+ assertEquals(ONSProfileDownloader.DownloadRetryResultCode
.ERR_MEMORY_FULL, res);
res = downloadHandler.mapDownloaderErrorCode(
EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
EuiccManager.OPERATION_SIM_SLOT,
EuiccManager.ERROR_TIME_OUT);
- assertEquals(ONSProfileDownloader.DownloadRetryOperationCode
+ assertEquals(ONSProfileDownloader.DownloadRetryResultCode
.ERR_RETRY_DOWNLOAD, res);
res = downloadHandler.mapDownloaderErrorCode(
EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
EuiccManager.OPERATION_SMDX,
EuiccManager.ERROR_CONNECTION_ERROR);
- assertEquals(ONSProfileDownloader.DownloadRetryOperationCode
+ assertEquals(ONSProfileDownloader.DownloadRetryResultCode
.ERR_RETRY_DOWNLOAD, res);
res = downloadHandler.mapDownloaderErrorCode(
EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
EuiccManager.OPERATION_SMDX,
EuiccManager.ERROR_INVALID_RESPONSE);
- assertEquals(ONSProfileDownloader.DownloadRetryOperationCode
+ assertEquals(ONSProfileDownloader.DownloadRetryResultCode
.ERR_UNRESOLVABLE, res);
res = downloadHandler.mapDownloaderErrorCode(
EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 0,
EuiccManager.OPERATION_SMDX,
EuiccManager.ERROR_INVALID_RESPONSE);
- assertEquals(ONSProfileDownloader.DownloadRetryOperationCode
+ assertEquals(ONSProfileDownloader.DownloadRetryResultCode
.ERR_UNRESOLVABLE, res);
res = downloadHandler.mapDownloaderErrorCode(
EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 0xA810048,
EuiccManager.OPERATION_SMDX_SUBJECT_REASON_CODE, 0);
- assertEquals(ONSProfileDownloader.DownloadRetryOperationCode
+ assertEquals(ONSProfileDownloader.DownloadRetryResultCode
.ERR_MEMORY_FULL, res);
synchronized (lock) {
@@ -595,6 +592,99 @@ public class ONSProfileDownloaderTest extends ONSBaseTest {
workerThread.exit();
}
+ @Test
+ public void testMultipleDownloadRequests() {
+ doReturn(TEST_SUB_ID).when(mMockSubInfo).getSubscriptionId();
+ PersistableBundle config = new PersistableBundle();
+ config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
+ doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
+
+ ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
+ mMockCarrierConfigManager, mMockEUICCManager, mMockONSProfileConfig,
+ mMockDownloadListener);
+
+ //When multiple download requests are received, download should be triggered only once.
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ verify(mMockEUICCManager, times(1)).downloadSubscription(any(), eq(true), any());
+
+ //Simulate response for download request from LPA.
+ Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
+ intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
+ intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
+ intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
+ intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
+ ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
+ intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE,
+ EuiccManager.OPERATION_DOWNLOAD);
+
+ onsProfileDownloader.onCallbackIntentReceived(intent,
+ EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK);
+
+ //Trigger new download after a sec
+ try {
+ Thread.sleep(1000);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ //After download response is received, new download requests should be processed.
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ verify(mMockEUICCManager, times(1)).downloadSubscription(any(), eq(true), any());
+ }
+
+ @Test
+ public void testDownloadRequestFailures() {
+ doReturn(TEST_SUB_ID).when(mMockSubInfo).getSubscriptionId();
+ PersistableBundle invalidConfig = new PersistableBundle();
+ invalidConfig.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, "");
+
+ PersistableBundle validConfig = new PersistableBundle();
+ validConfig.putString(
+ CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
+
+ // Only the first download request, will receive invalid SMDP server address.
+ doReturn(invalidConfig, validConfig)
+ .when(mMockCarrierConfigManager)
+ .getConfigForSubId(TEST_SUB_ID);
+
+ ONSProfileDownloader onsProfileDownloader =
+ new ONSProfileDownloader(
+ mContext,
+ mMockCarrierConfigManager,
+ mMockEUICCManager,
+ mMockONSProfileConfig,
+ mMockDownloadListener);
+
+ // First download request to be failed with INVALID_SMDP_ADDRESS error because of empty SMDP
+ // server address in configuration.
+ DownloadProfileResult retryResultCode =
+ onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ assertEquals(DownloadProfileResult.INVALID_SMDP_ADDRESS, retryResultCode);
+
+ verify(mMockEUICCManager, never()).downloadSubscription(any(), eq(true), any());
+
+ // Second Download request should be success and processed to EuiccManager.
+ retryResultCode = onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ assertEquals(DownloadProfileResult.SUCCESS, retryResultCode);
+ verify(mMockEUICCManager).downloadSubscription(any(), eq(true), any());
+
+ // Since download request is in progress, no further request to be sent to EuiccManager.
+ // They should return with DUPLICATE_REQUEST error.
+ retryResultCode = onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ assertEquals(DownloadProfileResult.DUPLICATE_REQUEST, retryResultCode);
+
+ retryResultCode = onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
+ assertEquals(DownloadProfileResult.DUPLICATE_REQUEST, retryResultCode);
+
+ verify(mMockEUICCManager).downloadSubscription(any(), eq(true), any());
+ }
+
@After
public void tearDown() throws Exception {
super.tearDown();
diff --git a/tests/src/com/android/ons/ONSProfileSelectorTest.java b/tests/src/com/android/ons/ONSProfileSelectorTest.java
index e86726a..68925f7 100644
--- a/tests/src/com/android/ons/ONSProfileSelectorTest.java
+++ b/tests/src/com/android/ons/ONSProfileSelectorTest.java
@@ -25,11 +25,16 @@ import android.os.Looper;
import android.os.ServiceManager;
import android.telephony.AvailableNetworkInfo;
import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityNr;
import android.telephony.CellInfo;
import android.telephony.CellInfoLte;
+import android.telephony.CellInfoNr;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.UiccCardInfo;
+import android.telephony.UiccPortInfo;
+import android.telephony.euicc.EuiccManager;
import android.util.Log;
import com.android.internal.telephony.ISub;
@@ -43,6 +48,7 @@ import org.mockito.MockitoAnnotations;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -54,6 +60,8 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
private int mDataSubId;
private int mResult;
@Mock
+ EuiccManager mMockEuiccManager;
+ @Mock
ONSNetworkScanCtlr mONSNetworkScanCtlr;
@Mock
TelephonyManager mSubscriptionBoundTelephonyManager;
@@ -160,6 +168,18 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
availableNetworkInfos.add(availableNetworkInfo);
+ UiccPortInfo uiccPortInfo = new UiccPortInfo("", 1, 1, false);
+ ArrayList<UiccPortInfo> uiccPortInfoList = new ArrayList<>();
+ uiccPortInfoList.add(uiccPortInfo);
+
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(true, 1, "", 0, false, true, uiccPortInfoList);
+ ArrayList<UiccCardInfo> uiccCardInfoList = new ArrayList<>();
+ uiccCardInfoList.add(uiccCardInfo);
+
+ doReturn(uiccCardInfoList).when(mMockTelephonyManager).getUiccCardsInfo();
+ doReturn(mMockEuiccManager).when(mMockEuiccManager).createForCardId(1);
+ doReturn(true).when(mMockEuiccManager).isSimPortAvailable(1);
+
IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
@Override
public void onComplete(int result) {
@@ -180,6 +200,8 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
.getOpportunisticSubscriptions();
mONSProfileSelector = new MyONSProfileSelector(mContext,
mONSProfileSelectionCallback);
+ mONSProfileSelector.mTelephonyManager = mMockTelephonyManager;
+ mONSProfileSelector.mEuiccManager = mMockEuiccManager;
mONSProfileSelector.updateOppSubs();
mONSProfileSelector.startProfileSelection(availableNetworkInfos, mCallback);
mLooper = Looper.myLooper();
@@ -203,13 +225,17 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
@Test
public void testStartProfileSelectionSuccess() {
int subId = 5;
- List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
- SubscriptionInfo subscriptionInfo = new SubscriptionInfo(subId, "", 1, "TMO", "TMO", 1, 1,
- "123", 1, null, "310", "210", "", false, null, "1");
- SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
- "123", 1, null, "310", "211", "", false, null, "1");
- subscriptionInfoList.add(subscriptionInfo);
- doReturn(subscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(subId);
+ List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ List<SubscriptionInfo> oppSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ SubscriptionInfo subscriptionInfo1 = new SubscriptionInfo(subId, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1, 1, 1,
+ null, null, false, 0);
+ SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo(6, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "211", "", true, null, "1", 1, false, null, false, 1, 1, 1,
+ null, null, false, 0);
+ oppSubscriptionInfoList.add(subscriptionInfo1);
+ activeSubscriptionInfoList.add(subscriptionInfo1);
+ activeSubscriptionInfoList.add(subscriptionInfo2);
List<CellInfo> results2 = new ArrayList<CellInfo>();
CellIdentityLte cellIdentityLte = new CellIdentityLte(310, 210, 1, 1, 1);
@@ -236,8 +262,14 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
@Override
public void run() {
Looper.prepare();
- doReturn(subscriptionInfoList).when(mSubscriptionManager)
+ doReturn(subscriptionInfo1).when(mSubscriptionManager)
+ .getActiveSubscriptionInfo(subId);
+ doReturn(oppSubscriptionInfoList).when(mSubscriptionManager)
.getOpportunisticSubscriptions();
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getActiveSubscriptionInfoList();
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
doReturn(true).when(mSubscriptionManager).isActiveSubId(subId);
doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
anyInt(), anyBoolean());
@@ -280,13 +312,18 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
- "123", 1, null, "310", "210", "", false, null, "1");
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1, 1, 1,
+ null, null, false, 0);
subscriptionInfoList.add(subscriptionInfo);
SubscriptionInfo subscriptionInfo_2 = new SubscriptionInfo(8, "", 1, "Vzw", "Vzw", 1, 1,
- "123", 1, null, "311", "480", "", false, null, "1");
+ "456", 1, null, "311", "480", "", true, null, "1", 1, true, null, false, 1, 1, 1,
+ null, null, false, 1);
subscriptionInfoList.add(subscriptionInfo_2);
doReturn(subscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(5);
doReturn(subscriptionInfo_2).when(mSubscriptionManager).getActiveSubscriptionInfo(8);
+ doReturn(subscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
+ doReturn(subscriptionInfoList).when(mSubscriptionManager).getOpportunisticSubscriptions();
List<CellInfo> results2 = new ArrayList<CellInfo>();
CellIdentityLte cellIdentityLte = new CellIdentityLte(310, 210, 1, 1, 1);
@@ -323,8 +360,6 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
@Override
public void run() {
Looper.prepare();
- doReturn(subscriptionInfoList).when(mSubscriptionManager)
- .getOpportunisticSubscriptions();
doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
anyInt(), anyBoolean());
@@ -354,13 +389,16 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
public void testStartProfileSelectionWithActivePrimarySimOnESim() {
List<SubscriptionInfo> opportunisticSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
- SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
- "123", 1, null, "310", "210", "", true, null, "1", true, null, 1839, 1);
+ SubscriptionInfo subscriptionInfo1 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, 1);
SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo(6, "", 1, "TMO", "TMO", 1, 1,
- "123", 1, null, "310", "211", "", true, null, "1", false, null, 1839, 1);
- opportunisticSubscriptionInfoList.add(subscriptionInfo);
+ "456", 1, null, "310", "211", "", true, null, "1", 1, false, null, false, 1839, 1,
+ 1, null, null, false, 2);
+
+ activeSubscriptionInfoList.add(subscriptionInfo1);
activeSubscriptionInfoList.add(subscriptionInfo2);
- doReturn(subscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(5);
+ doReturn(subscriptionInfo1).when(mSubscriptionManager).getActiveSubscriptionInfo(5);
doReturn(subscriptionInfo2).when(mSubscriptionManager).getActiveSubscriptionInfo(6);
ArrayList<String> mccMncs = new ArrayList<>();
@@ -370,6 +408,19 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
ArrayList<AvailableNetworkInfo> availableNetworkInfos = new ArrayList<AvailableNetworkInfo>();
availableNetworkInfos.add(availableNetworkInfo);
+ ArrayList<UiccPortInfo> uiccPortInfoList = new ArrayList<>();
+ uiccPortInfoList.add(new UiccPortInfo("1", 0, 0, false));
+ uiccPortInfoList.add(new UiccPortInfo("2", 1, 1, true));
+
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(
+ true, 1, "1", 0, false, true, uiccPortInfoList);
+ ArrayList<UiccCardInfo> uiccCardInfoList = new ArrayList<>();
+ uiccCardInfoList.add(uiccCardInfo);
+
+ doReturn(uiccCardInfoList).when(mMockTelephonyManager).getUiccCardsInfo();
+ doReturn(mMockEuiccManager).when(mMockEuiccManager).createForCardId(1);
+ doReturn(true).when(mMockEuiccManager).isSimPortAvailable(1);
+
IUpdateAvailableNetworksCallback mCallback = new IUpdateAvailableNetworksCallback.Stub() {
@Override
public void onComplete(int result) {
@@ -388,12 +439,18 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
doReturn(false).when(mSubscriptionManager).isActiveSubId(anyInt());
doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
.getActiveSubscriptionInfoList(anyBoolean());
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getActiveSubscriptionInfoList();
+ doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
+ anyInt(), anyBoolean());
mONSProfileSelector = new MyONSProfileSelector(mContext,
new MyONSProfileSelector.ONSProfileSelectionCallback() {
public void onProfileSelectionDone() {
setReady(true);
}
});
+ mONSProfileSelector.mTelephonyManager = mMockTelephonyManager;
+ mONSProfileSelector.mEuiccManager = mMockEuiccManager;
mONSProfileSelector.updateOppSubs();
mONSProfileSelector.startProfileSelection(availableNetworkInfos, mCallback);
mLooper = Looper.myLooper();
@@ -415,7 +472,8 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
callbackIntent.putExtra("sequenceId", 1);
callbackIntent.putExtra("subId", 5);
waitUntilReady();
- assertEquals(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS, mResult);
+ assertEquals(TelephonyManager.UPDATE_AVAILABLE_NETWORKS_NO_OPPORTUNISTIC_SUB_AVAILABLE,
+ mResult);
}
public static void waitForMs(long ms) {
@@ -559,15 +617,24 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
@Test
public void testStartProfileSelectionSuccessWithSameArgumentsAgain() {
- List<SubscriptionInfo> subscriptionInfoList = new ArrayList<SubscriptionInfo>();
- SubscriptionInfo subscriptionInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
- "123", 1, null, "310", "210", "", false, null, "1");
+ List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ List<SubscriptionInfo> oppSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ SubscriptionInfo subscriptionInfo1 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1, 1, 1,
+ null, null, false, 0);
SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo(6, "", 1, "TMO", "TMO", 1, 1,
- "123", 1, null, "310", "211", "", false, null, "1");
- subscriptionInfoList.add(subscriptionInfo);
- doReturn(subscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(5);
+ "123", 1, null, "310", "211", "", true, null, "1", 1, false, null, false, 1, 1, 1,
+ null, null, false, 0);
+
+ oppSubscriptionInfoList.add(subscriptionInfo1);
+ doReturn(subscriptionInfo1).when(mSubscriptionManager).getActiveSubscriptionInfo(5);
doReturn(subscriptionInfo2).when(mSubscriptionManager).getActiveSubscriptionInfo(6);
+ activeSubscriptionInfoList.add(subscriptionInfo1);
+ activeSubscriptionInfoList.add(subscriptionInfo2);
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
+
List<CellInfo> results2 = new ArrayList<CellInfo>();
CellIdentityLte cellIdentityLte = new CellIdentityLte(310, 210, 1, 1, 1);
CellInfoLte cellInfoLte = new CellInfoLte();
@@ -599,7 +666,7 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
@Override
public void run() {
Looper.prepare();
- doReturn(subscriptionInfoList).when(mSubscriptionManager)
+ doReturn(oppSubscriptionInfoList).when(mSubscriptionManager)
.getOpportunisticSubscriptions();
doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
@@ -636,7 +703,7 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
@Override
public void run() {
Looper.prepare();
- doReturn(subscriptionInfoList).when(mSubscriptionManager)
+ doReturn(oppSubscriptionInfoList).when(mSubscriptionManager)
.getOpportunisticSubscriptions();
doReturn(true).when(mSubscriptionManager).isActiveSubId(anyInt());
doReturn(true).when(mSubscriptionBoundTelephonyManager).enableModemForSlot(
@@ -759,6 +826,233 @@ public class ONSProfileSelectorTest extends ONSBaseTest {
}).start();
waitUntilReady();
waitForMs(500);
- assertEquals(mONSProfileSelector.getCurrentPreferredData(), 5);
+ assertEquals(5, mONSProfileSelector.getCurrentPreferredData());
+ }
+
+ @Test
+ public void testAvailablePortWhenTwoPrimarySIMsAreActive() {
+ /**
+ * 2 - Primary active subscriptions and
+ * 1 - Inactive opportunistic subscription
+ */
+
+ List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ List<SubscriptionInfo> opportunisticInfoList = new ArrayList<SubscriptionInfo>();
+
+ SubscriptionInfo oppSubInfo = new SubscriptionInfo(4, "", -1, "TMO", "TMO", 1, 1,
+ "001", 1, null, "110", "210", "", true, null, "1", 1, true, null, false, 2839, 1,
+ 1, null, null, false, TelephonyManager.INVALID_PORT_INDEX);
+
+ SubscriptionInfo primarySubInfo1 = new SubscriptionInfo(5, "", 0, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, false, null, false, 1839, 1,
+ 1, null, null, false, 0);
+ SubscriptionInfo primarySubInfo2 = new SubscriptionInfo(6, "", 0, "TMO", "TMO", 1, 1,
+ "456", 1, null, "310", "211", "", true, null, "1", 1, false, null, false, 1839, 1,
+ 1, null, null, false, 1);
+
+ activeSubscriptionInfoList.add(primarySubInfo1);
+ activeSubscriptionInfoList.add(primarySubInfo2);
+ opportunisticInfoList.add(oppSubInfo);
+
+ doReturn(opportunisticInfoList).when(mSubscriptionManager).getOpportunisticSubscriptions();
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
+
+ UiccPortInfo uiccPortInfo1 = new UiccPortInfo("", 0, 0, true);
+ UiccPortInfo uiccPortInfo2 = new UiccPortInfo("", 1, 0, true);
+ ArrayList<UiccPortInfo> uiccPortInfoList = new ArrayList<>();
+ uiccPortInfoList.add(uiccPortInfo1);
+ uiccPortInfoList.add(uiccPortInfo2);
+
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(true, 1, "", 0, false, true, uiccPortInfoList);
+ ArrayList<UiccCardInfo> uiccCardInfoList = new ArrayList<>();
+ uiccCardInfoList.add(uiccCardInfo);
+
+ doReturn(uiccCardInfoList).when(mMockTelephonyManager).getUiccCardsInfo();
+ doReturn(mMockEuiccManager).when(mMockEuiccManager).createForCardId(1);
+ doReturn(false).when(mMockEuiccManager).isSimPortAvailable(0);
+ doReturn(false).when(mMockEuiccManager).isSimPortAvailable(1);
+
+ mONSProfileSelector = new MyONSProfileSelector(mContext, null);
+ mONSProfileSelector.mTelephonyManager = mMockTelephonyManager;
+ mONSProfileSelector.mEuiccManager = mMockEuiccManager;
+
+ int portIdx = mONSProfileSelector.getAvailableESIMPortIndex();
+ assertEquals(TelephonyManager.INVALID_PORT_INDEX, portIdx);
+ }
+
+ @Test
+ public void testAvailablePortWhenOpportunisticEsimIsActive() {
+ /**
+ * 1 - Primary active subscriptions and
+ * 1 - Active opportunistic subscription
+ */
+
+ List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ List<SubscriptionInfo> opportunisticInfoList = new ArrayList<SubscriptionInfo>();
+
+ SubscriptionInfo oppSubInfo = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, 0);
+
+ SubscriptionInfo primarySubInfo = new SubscriptionInfo(6, "", 1, "TMO", "TMO", 1, 1,
+ "456", 1, null, "310", "211", "", true, null, "1", 1, false, null, false, 1839, 1,
+ 1, null, null, false, 1);
+
+ opportunisticInfoList.add(oppSubInfo);
+ activeSubscriptionInfoList.add(oppSubInfo);
+ activeSubscriptionInfoList.add(primarySubInfo);
+
+ doReturn(opportunisticInfoList).when(mSubscriptionManager)
+ .getOpportunisticSubscriptions();
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
+
+ mONSProfileSelector = new MyONSProfileSelector(mContext, null);
+ int portIdx = mONSProfileSelector.getAvailableESIMPortIndex();
+ assertEquals(0, portIdx);
+ }
+
+ @Test
+ public void testAvailablePortWhenTwoOpportunisticEsimsAreActive() {
+ /**
+ * 2 - Active opportunistic subscriptions.
+ */
+
+ List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ List<SubscriptionInfo> opportunisticInfoList = new ArrayList<SubscriptionInfo>();
+
+ SubscriptionInfo opportunisticSubInfo1 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, 0);
+
+ SubscriptionInfo opportunisticSubInfo2 = new SubscriptionInfo(6, "", 1, "TMO", "TMO", 1, 1,
+ "456", 1, null, "310", "211", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, 1);
+
+ opportunisticInfoList.add(opportunisticSubInfo1);
+ opportunisticInfoList.add(opportunisticSubInfo2);
+ activeSubscriptionInfoList.add(opportunisticSubInfo1);
+ activeSubscriptionInfoList.add(opportunisticSubInfo2);
+
+ doReturn(opportunisticInfoList).when(mSubscriptionManager)
+ .getOpportunisticSubscriptions();
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
+
+ mONSProfileSelector = new MyONSProfileSelector(mContext, null);
+ int portIdx = mONSProfileSelector.getAvailableESIMPortIndex();
+
+ /* one of the opportunistic eSIM port should be selected */
+ assertTrue(portIdx == 0 || portIdx == 1);
+ }
+
+ @Test
+ public void testAvailablePortWhenOpportunisticEsimIsActiveAndInactiveSubscriptions() {
+ /**
+ * 1 - Primary active subscription and
+ * 1 - Active opportunistic subscription and
+ * 2 - Inactive opportunistic subscriptions
+ */
+
+ List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ List<SubscriptionInfo> opportunisticInfoList = new ArrayList<SubscriptionInfo>();
+
+ SubscriptionInfo opportunisticSubInfo1 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, 1);
+ SubscriptionInfo primarySubInfo = new SubscriptionInfo(6, "", 1, "TMO", "TMO", 1, 1,
+ "456", 1, null, "310", "211", "", true, null, "1", 1, false, null, false, 1839, 1,
+ 1, null, null, false, 0);
+
+ SubscriptionInfo opportunisticSubInfo2 = new SubscriptionInfo(7, "", 1, "TMO", "TMO", 1, 1,
+ "789", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, TelephonyManager.INVALID_PORT_INDEX);
+
+ SubscriptionInfo oppSubInfo3 = new SubscriptionInfo(8, "", 1, "TMO", "TMO", 1, 1,
+ "012", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, TelephonyManager.INVALID_PORT_INDEX);
+
+ opportunisticInfoList.add(opportunisticSubInfo1);
+ opportunisticInfoList.add(opportunisticSubInfo2);
+ opportunisticInfoList.add(oppSubInfo3);
+ activeSubscriptionInfoList.add(opportunisticSubInfo1);
+ activeSubscriptionInfoList.add(primarySubInfo);
+
+ doReturn(opportunisticInfoList).when(mSubscriptionManager)
+ .getOpportunisticSubscriptions();
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
+
+ mONSProfileSelector = new MyONSProfileSelector(mContext, null);
+ int portIdx = mONSProfileSelector.getAvailableESIMPortIndex();
+ assertEquals(1, portIdx);
+ }
+
+ @Test
+ public void testAvailablePortWhenOnlyInactiveSubscriptions() {
+ /**
+ * 1 - Primary inactive subscription and
+ * 2 - Inactive opportunistic subscriptions
+ */
+
+ List<SubscriptionInfo> activeSubscriptionInfoList = new ArrayList<SubscriptionInfo>();
+ List<SubscriptionInfo> opportunisticInfoList = new ArrayList<SubscriptionInfo>();
+
+ SubscriptionInfo oppSubInfo1 = new SubscriptionInfo(5, "", 1, "TMO", "TMO", 1, 1,
+ "123", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, TelephonyManager.INVALID_PORT_INDEX);
+
+ // Not used in activeSubscriptionInfoList or opportunisticInfoList
+ /*SubscriptionInfo primarySubInfo = new SubscriptionInfo(6, "", 1, "TMO", "TMO", 1, 1,
+ "456", 1, null, "310", "211", "", true, null, "1", 1, false, null, false, 1839, 1,
+ 1, null, null, false, 2);*/
+
+ SubscriptionInfo oppSubInfo2 = new SubscriptionInfo(7, "", 1, "TMO", "TMO", 1, 1,
+ "789", 1, null, "310", "210", "", true, null, "1", 1, true, null, false, 1839, 1,
+ 1, null, null, false, TelephonyManager.INVALID_PORT_INDEX);
+
+ opportunisticInfoList.add(oppSubInfo1);
+ opportunisticInfoList.add(oppSubInfo2);
+
+ doReturn(opportunisticInfoList).when(mSubscriptionManager)
+ .getOpportunisticSubscriptions();
+ doReturn(activeSubscriptionInfoList).when(mSubscriptionManager)
+ .getCompleteActiveSubscriptionInfoList();
+
+ UiccPortInfo uiccPortInfo1 = new UiccPortInfo("", 0, 0, false);
+ UiccPortInfo uiccPortInfo2 = new UiccPortInfo("", 1, 0, false);
+ ArrayList<UiccPortInfo> uiccPortInfoList = new ArrayList<>();
+ uiccPortInfoList.add(uiccPortInfo1);
+ uiccPortInfoList.add(uiccPortInfo2);
+
+ UiccCardInfo uiccCardInfo = new UiccCardInfo(true, 1, "", 0, false, true, uiccPortInfoList);
+ ArrayList<UiccCardInfo> uiccCardInfoList = new ArrayList<>();
+ uiccCardInfoList.add(uiccCardInfo);
+
+ doReturn(uiccCardInfoList).when(mMockTelephonyManager).getUiccCardsInfo();
+ doReturn(mMockEuiccManager).when(mMockEuiccManager).createForCardId(1);
+ doReturn(true).when(mMockEuiccManager).isSimPortAvailable(0);
+ doReturn(true).when(mMockEuiccManager).isSimPortAvailable(1);
+
+ mONSProfileSelector = new MyONSProfileSelector(mContext, null);
+ mONSProfileSelector.mTelephonyManager = mMockTelephonyManager;
+ mONSProfileSelector.mEuiccManager = mMockEuiccManager;
+
+ int portIdx = mONSProfileSelector.getAvailableESIMPortIndex();
+ assertTrue(portIdx == 0 || portIdx == 1);
+ }
+
+ @Test
+ public void testGetMncMccFromCellInfoNr() {
+ mONSProfileSelector = new MyONSProfileSelector(mContext, null);
+
+ CellIdentityNr cellIdentityNr = new CellIdentityNr(0, 0, 0, new int[]{0}, "111", "222", 0,
+ "", "", Collections.emptyList());
+
+ CellInfoNr cellinfoNr = new CellInfoNr(0, true, 0, cellIdentityNr, null);
+
+ assertEquals(mONSProfileSelector.getMcc(cellinfoNr), "111");
+ assertEquals(mONSProfileSelector.getMnc(cellinfoNr), "222");
}
}
diff --git a/tests/src/com/android/ons/ONSStatsInfoTest.java b/tests/src/com/android/ons/ONSStatsInfoTest.java
new file mode 100644
index 0000000..3cd0456
--- /dev/null
+++ b/tests/src/com/android/ons/ONSStatsInfoTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 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.ons;
+
+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.ons.ONSProfileActivator.Result;
+import com.android.ons.ONSProfileDownloader.DownloadRetryResultCode;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ONSStatsInfoTest {
+
+ @Test
+ public void testProvisioningResult() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setProvisioningResult(Result.ERR_AUTO_PROVISIONING_DISABLED);
+ assertEquals(Result.ERR_AUTO_PROVISIONING_DISABLED, info.getProvisioningResult());
+ assertNull(info.getDownloadResult());
+ assertTrue(info.isProvisioningResultUpdated());
+ }
+
+ @Test
+ public void testDownloadResult() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setDownloadResult(DownloadRetryResultCode.ERR_MEMORY_FULL);
+ assertEquals(DownloadRetryResultCode.ERR_MEMORY_FULL, info.getDownloadResult());
+ assertNull(info.getProvisioningResult());
+ assertFalse(info.isProvisioningResultUpdated());
+ }
+
+ @Test
+ public void testPrimarySimSubId() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setPrimarySimSubId(1);
+ assertEquals(1, info.getPrimarySimSubId());
+ }
+
+ @Test
+ public void testOppSimCarrierId() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setOppSimCarrierId(1221);
+ assertEquals(1221, info.getOppSimCarrierId());
+ }
+
+ @Test
+ public void testRetryCount() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setRetryCount(3);
+ assertEquals(3, info.getRetryCount());
+ }
+
+ @Test
+ public void testDetailedErrCode() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setDetailedErrCode(1000);
+ assertEquals(1000, info.getDetailedErrCode());
+ }
+
+ @Test
+ public void testIsWifiConnected() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setWifiConnected(true);
+ assertTrue(info.isWifiConnected());
+ }
+
+ @Test
+ public void testIsProvisioningResultUpdated() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setProvisioningResult(Result.ERR_ESIM_NOT_SUPPORTED);
+ assertTrue(info.isProvisioningResultUpdated());
+
+ info.setDownloadResult(DownloadRetryResultCode.ERR_MEMORY_FULL);
+ assertFalse(info.isProvisioningResultUpdated());
+ }
+}
diff --git a/tests/src/com/android/ons/ONSStatsTest.java b/tests/src/com/android/ons/ONSStatsTest.java
new file mode 100644
index 0000000..12c49af
--- /dev/null
+++ b/tests/src/com/android/ons/ONSStatsTest.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2022 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.ons;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+
+import com.android.ons.ONSProfileActivator.Result;
+import com.android.ons.ONSProfileDownloader.DownloadRetryResultCode;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public class ONSStatsTest {
+
+ private static final String ONS_ATOM_LOG_FILE = "ons_atom_log_info";
+ private static final String KEY_DETAILED_ERROR_CODE = "_detailed_error_code";
+
+ @Spy private Context mContext;
+ @Mock private SubscriptionManager mSubscriptionManager;
+ private SharedPreferences mSharedPreferences;
+ @Mock private SubscriptionInfo mSubInfoId1;
+ @Mock private SubscriptionInfo mSubInfoId2;
+ private ONSStats mONSStats;
+
+ private class FakeSharedPreferences implements SharedPreferences {
+ HashMap<String, Object> mMap = new HashMap<>();
+
+ @Override
+ public Map<String, ?> getAll() {
+ return mMap;
+ }
+
+ @Override
+ public String getString(String key, String defValue) {
+ return (String) mMap.getOrDefault(key, defValue);
+ }
+
+ @Override
+ public Set<String> getStringSet(String key, Set<String> defValues) {
+ if (mMap.containsKey(key)) {
+ return (Set<String>) mMap.get(key);
+ }
+ return defValues;
+ }
+
+ @Override
+ public int getInt(String key, int defValue) {
+ return (int) mMap.getOrDefault(key, defValue);
+ }
+
+ @Override
+ public long getLong(String key, long defValue) {
+ return 0; // not used
+ }
+
+ @Override
+ public float getFloat(String key, float defValue) {
+ return (float) mMap.getOrDefault(key, defValue);
+ }
+
+ @Override
+ public boolean getBoolean(String key, boolean defValue) {
+ return (boolean) mMap.getOrDefault(key, defValue);
+ }
+
+ @Override
+ public boolean contains(String key) {
+ return mMap.containsKey(key);
+ }
+
+ @Override
+ public Editor edit() {
+ TestEditor editor = new TestEditor();
+ editor.map = mMap;
+ return editor;
+ }
+
+ @Override
+ public void registerOnSharedPreferenceChangeListener(
+ OnSharedPreferenceChangeListener listener) {}
+
+ @Override
+ public void unregisterOnSharedPreferenceChangeListener(
+ OnSharedPreferenceChangeListener listener) {}
+
+ private class TestEditor implements SharedPreferences.Editor {
+ HashMap<String, Object> map = new HashMap<>();
+
+ @Override
+ public SharedPreferences.Editor putString(String key, String value) {
+ map.put(key, value);
+ return this;
+ }
+
+ @Override
+ public SharedPreferences.Editor putStringSet(String key, Set<String> values) {
+ map.put(key, values);
+ return this;
+ }
+
+ @Override
+ public SharedPreferences.Editor putInt(String key, int value) {
+ map.put(key, value);
+ return this;
+ }
+
+ @Override
+ public SharedPreferences.Editor putLong(String key, long value) {
+ map.put(key, value);
+ return this;
+ }
+
+ @Override
+ public SharedPreferences.Editor putFloat(String key, float value) {
+ map.put(key, value);
+ return this;
+ }
+
+ @Override
+ public SharedPreferences.Editor putBoolean(String key, boolean value) {
+ map.put(key, value);
+ return this;
+ }
+
+ @Override
+ public SharedPreferences.Editor remove(String key) {
+ map.remove(key);
+ return this;
+ }
+
+ @Override
+ public SharedPreferences.Editor clear() {
+ map.clear();
+ return this;
+ }
+
+ @Override
+ public boolean commit() {
+ mMap = map;
+ return true;
+ }
+
+ @Override
+ public void apply() {
+ mMap = map;
+ }
+ }
+ ;
+ }
+ ;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mSharedPreferences = new FakeSharedPreferences();
+ doReturn(mSharedPreferences)
+ .when(mContext)
+ .getSharedPreferences(eq(ONS_ATOM_LOG_FILE), eq(Context.MODE_PRIVATE));
+ doReturn(123).when(mSubInfoId1).getCarrierId();
+ doReturn(456).when(mSubInfoId2).getCarrierId();
+ doReturn(mSubInfoId1).when(mSubscriptionManager).getActiveSubscriptionInfo(1);
+ doReturn(mSubInfoId2).when(mSubscriptionManager).getActiveSubscriptionInfo(2);
+ mONSStats = new ONSStats(mContext, mSubscriptionManager);
+ }
+
+ @After
+ public void tearDown() {
+ mSharedPreferences.edit().clear().apply();
+ }
+
+ @Test
+ public void testLogEvent() {
+ ONSStatsInfo info =
+ new ONSStatsInfo()
+ .setPrimarySimSubId(1)
+ .setProvisioningResult(Result.ERR_CANNOT_SWITCH_TO_DUAL_SIM_MODE);
+ assertTrue(mONSStats.logEvent(info));
+ }
+
+ @Test
+ public void testIgnoredLogEvents() {
+ // ignored error codes should not log.
+ ONSStatsInfo info = new ONSStatsInfo().setProvisioningResult(Result.DOWNLOAD_REQUESTED);
+ assertFalse(mONSStats.logEvent(info));
+
+ info = new ONSStatsInfo().setProvisioningResult(Result.ERR_NO_SIM_INSERTED);
+ assertFalse(mONSStats.logEvent(info));
+
+ info = new ONSStatsInfo().setProvisioningResult(Result.ERR_DUPLICATE_DOWNLOAD_REQUEST);
+ assertFalse(mONSStats.logEvent(info));
+
+ info = new ONSStatsInfo().setProvisioningResult(Result.ERR_SWITCHING_TO_DUAL_SIM_MODE);
+ assertFalse(mONSStats.logEvent(info));
+ }
+
+ @Test
+ public void testRepeatedLogEvents() {
+ ONSStatsInfo info;
+ info =
+ new ONSStatsInfo()
+ .setDownloadResult(DownloadRetryResultCode.ERR_MEMORY_FULL)
+ .setDetailedErrCode(10011);
+ assertTrue(mONSStats.logEvent(info));
+
+ // same result should not log consecutively
+ assertFalse(mONSStats.logEvent(info));
+ assertFalse(mONSStats.logEvent(info));
+ }
+
+ @Test
+ public void testRepeatedAllowedLogEvents() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setProvisioningResult(Result.ERR_DOWNLOADED_ESIM_NOT_FOUND);
+ assertTrue(mONSStats.logEvent(info));
+
+ // ERR_DOWNLOADED_ESIM_NOT_FOUND is allowed to log consecutively
+ assertTrue(mONSStats.logEvent(info));
+ assertTrue(mONSStats.logEvent(info));
+
+ info =
+ new ONSStatsInfo()
+ .setDownloadResult(DownloadRetryResultCode.ERR_INSTALL_ESIM_PROFILE_FAILED);
+ assertTrue(mONSStats.logEvent(info));
+
+ // ERR_INSTALL_ESIM_PROFILE_FAILED is allowed to log consecutively
+ assertTrue(mONSStats.logEvent(info));
+ assertTrue(mONSStats.logEvent(info));
+ }
+
+ @Test
+ public void testRepeatedSuccessLogEvents() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setProvisioningResult(Result.SUCCESS).setRetryCount(2);
+
+ // should log every time if eSIM is newly downloaded.
+ assertTrue(mONSStats.logEvent(info));
+ assertTrue(mONSStats.logEvent(info));
+
+ info = new ONSStatsInfo().setProvisioningResult(Result.SUCCESS);
+ // should log even if eSIM is already downloaded and event triggered just to group it.
+ assertTrue(mONSStats.logEvent(info));
+ assertTrue(mONSStats.logEvent(info));
+ }
+
+ @Test
+ public void testRepeatedErrorWithInfoChangeLogEvents() {
+ ONSStatsInfo info =
+ new ONSStatsInfo()
+ .setPrimarySimSubId(1)
+ .setProvisioningResult(Result.ERR_AUTO_PROVISIONING_DISABLED);
+ assertTrue(mONSStats.logEvent(info));
+
+ // Same error should log if the info is changed.
+ info.setPrimarySimSubId(2);
+ assertTrue(mONSStats.logEvent(info));
+
+ // no change in info
+ assertFalse(mONSStats.logEvent(info));
+ }
+
+ @Test
+ public void testDetailedErrorCodeLogEvents() {
+ ONSStatsInfo info;
+ info = new ONSStatsInfo().setProvisioningResult(Result.ERR_WAITING_FOR_INTERNET_CONNECTION);
+ assertTrue(mONSStats.logEvent(info));
+
+ // For provisioning errors; Result enum ordinal is set as detailed error code.
+ assertEquals(
+ Result.ERR_WAITING_FOR_INTERNET_CONNECTION.ordinal(),
+ mSharedPreferences.getInt(KEY_DETAILED_ERROR_CODE, -1));
+ assertEquals(
+ Result.ERR_WAITING_FOR_INTERNET_CONNECTION.ordinal(), info.getDetailedErrCode());
+
+ // For Download errors; detailed error code is updated from EuiccManager.
+ info =
+ new ONSStatsInfo()
+ .setDownloadResult(DownloadRetryResultCode.ERR_MEMORY_FULL)
+ .setDetailedErrCode(10223);
+ assertTrue(mONSStats.logEvent(info));
+ assertEquals(10223, mSharedPreferences.getInt(KEY_DETAILED_ERROR_CODE, -1));
+ assertEquals(10223, info.getDetailedErrCode());
+ }
+}
diff --git a/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java b/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java
index 0a75371..5b2d67c 100644
--- a/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java
+++ b/tests/src/com/android/ons/OpportunisticNetworkServiceTest.java
@@ -76,13 +76,26 @@ public class OpportunisticNetworkServiceTest extends ONSBaseTest {
mOpportunisticNetworkService = new OpportunisticNetworkService();
mOpportunisticNetworkService.initialize(mContext);
mOpportunisticNetworkService.mSubscriptionManager = mSubscriptionManager;
- iOpportunisticNetworkService = (IOns) mOpportunisticNetworkService.onBind(null);
+ for (int retry = 2; retry > 0; retry--) {
+
+ iOpportunisticNetworkService = (IOns) mOpportunisticNetworkService.onBind(null);
+
+ if (iOpportunisticNetworkService != null) {
+ break;
+ }
+
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ Log.e(TAG, e.toString());
+ }
+ }
mLooper = Looper.myLooper();
setReady(true);
Looper.loop();
}
}).start();
- waitUntilReady(200);
+ waitUntilReady(300);
}
@After
@@ -208,6 +221,7 @@ public class OpportunisticNetworkServiceTest extends ONSBaseTest {
};
try {
+ assertNotNull(iOpportunisticNetworkService);
iOpportunisticNetworkService.setPreferredDataSubscriptionId(5, false, callbackStub,
pkgForDebug);
} catch (RemoteException ex) {