• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ons;
18 
19 import static org.mockito.Mockito.any;
20 import static org.mockito.Mockito.doNothing;
21 import static org.mockito.Mockito.doReturn;
22 import static org.mockito.Mockito.eq;
23 import static org.mockito.Mockito.never;
24 import static org.mockito.Mockito.times;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.verifyZeroInteractions;
27 
28 import android.content.Context;
29 import android.content.Intent;
30 import android.os.Looper;
31 import android.os.PersistableBundle;
32 import android.telephony.CarrierConfigManager;
33 import android.telephony.SubscriptionInfo;
34 import android.telephony.SubscriptionManager;
35 import android.telephony.euicc.DownloadableSubscription;
36 import android.telephony.euicc.EuiccManager;
37 import android.util.Log;
38 import android.util.Pair;
39 
40 import com.android.ons.ONSProfileDownloader.DownloadProfileResult;
41 
42 import org.junit.After;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.mockito.Mock;
46 import org.mockito.MockitoAnnotations;
47 
48 public class ONSProfileDownloaderTest extends ONSBaseTest {
49     private static final String TAG = ONSProfileDownloaderTest.class.getName();
50     private static final int TEST_SUB_ID = 1;
51     private static final int TEST_EUICC_CARD_ID = 1;
52     private static final String TEST_SMDP_ADDRESS = "TEST-ESIM.COM";
53 
54     @Mock
55     Context mMockContext;
56     @Mock
57     EuiccManager mMockEuiccManager;
58     @Mock
59     EuiccManager mMockEuiccManagerForCard1;
60     @Mock
61     SubscriptionManager mMockSubManager;
62     @Mock
63     SubscriptionInfo mMockSubInfo;
64     @Mock
65     CarrierConfigManager mMockCarrierConfigManager;
66     @Mock
67     private ONSProfileConfigurator mMockONSProfileConfig;
68     @Mock
69     ONSProfileDownloader.IONSProfileDownloaderListener mMockDownloadListener;
70 
71     @Before
setUp()72     public void setUp() throws Exception {
73         super.setUp("ONSTest");
74         MockitoAnnotations.initMocks(this);
75         Looper.prepare();
76     }
77 
78     static class WorkerThread extends Thread {
79         Looper mWorkerLooper;
80         private final Runnable mRunnable;
81 
WorkerThread(Runnable runnable)82         WorkerThread(Runnable runnable) {
83             mRunnable = runnable;
84         }
85 
86         @Override
run()87         public void run() {
88             super.run();
89             Looper.prepare();
90             mWorkerLooper = Looper.myLooper();
91             mRunnable.run();
92             mWorkerLooper.loop();
93         }
94 
exit()95         public void exit() {
96             mWorkerLooper.quitSafely();
97         }
98     }
99 
100     @Test
testNullSMDPAddress()101     public void testNullSMDPAddress() {
102         doReturn(TEST_SUB_ID).when(mMockSubInfo).getSubscriptionId();
103         PersistableBundle config = new PersistableBundle();
104         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, null);
105         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
106         doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
107         doReturn(false).when(mMockSubInfo).isEmbedded();
108 
109         ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mMockContext,
110                 mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
111                 mMockONSProfileConfig, null);
112 
113         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
114 
115         verify(mMockEuiccManager, never()).downloadSubscription(null, true, null);
116     }
117 
118     @Test
testDownloadSuccessCallback()119     public void testDownloadSuccessCallback() {
120 
121         final Object lock = new Object();
122         final ONSProfileDownloader.IONSProfileDownloaderListener mListener =
123                 new ONSProfileDownloader.IONSProfileDownloaderListener() {
124                     @Override
125                     public void onDownloadComplete(int primarySubId) {
126                         assertEquals(primarySubId, TEST_SUB_ID);
127                         synchronized (lock) {
128                             lock.notify();
129                         }
130                     }
131 
132                     @Override
133                     public void onDownloadError(
134                             int pSIMSubId,
135                             ONSProfileDownloader.DownloadRetryResultCode operationCode,
136                             int detailedErrorCode) {
137 
138                     }
139                 };
140 
141         Runnable runnable = new Runnable() {
142             @Override
143             public void run() {
144                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
145                 doReturn(false).when(mMockSubInfo).isEmbedded();
146 
147                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mMockContext,
148                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
149                         mMockONSProfileConfig, mListener);
150 
151                 Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
152                 intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
153                 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
154                 intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
155                 intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
156                         ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
157                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE, 0);
158 
159                 onsProfileDownloader.onCallbackIntentReceived(intent,
160                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK);
161             }
162         };
163 
164         WorkerThread workerThread = new WorkerThread(runnable);
165         workerThread.start();
166 
167         synchronized (lock) {
168             try {
169                 lock.wait();
170             } catch (Exception e) {
171                 Log.e(TAG, e.getMessage());
172             }
173         }
174 
175         workerThread.exit();
176     }
177 
178     @Test
testDownloadFailureUnresolvableError()179     public void testDownloadFailureUnresolvableError() {
180         PersistableBundle config = new PersistableBundle();
181         config.putInt(CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 1);
182         config.putInt(CarrierConfigManager.KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 2);
183         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
184         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
185 
186         Runnable runnable = new Runnable() {
187             @Override
188             public void run() {
189                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
190                 doReturn(false).when(mMockSubInfo).isEmbedded();
191 
192                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mMockContext,
193                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
194                         mMockONSProfileConfig, mMockDownloadListener);
195 
196                 Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
197                 intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
198                 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
199                 intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
200                 intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
201                         ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
202 
203                 onsProfileDownloader.onCallbackIntentReceived(intent,
204                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR);
205             }
206         };
207 
208         WorkerThread workerThread = new WorkerThread(runnable);
209         workerThread.start();
210 
211         try {
212             Thread.sleep(3000);
213         } catch (Exception e) {
214             e.printStackTrace();
215         }
216 
217         verifyZeroInteractions(mMockEuiccManager);
218         workerThread.exit();
219     }
220 
221     @Test
testDownloadFailureMemoryFullError()222     public void testDownloadFailureMemoryFullError() {
223 
224         Runnable runnable = new Runnable() {
225             @Override
226             public void run() {
227                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
228                 doReturn(false).when(mMockSubInfo).isEmbedded();
229 
230                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mMockContext,
231                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
232                         mMockONSProfileConfig, mMockDownloadListener);
233 
234                 Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
235                 intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
236                 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
237                 intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
238                 intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
239                         ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
240                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE,
241                         EuiccManager.OPERATION_EUICC_GSMA);
242                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE,
243                         EuiccManager.ERROR_EUICC_INSUFFICIENT_MEMORY);
244 
245                 onsProfileDownloader.onCallbackIntentReceived(intent,
246                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR);
247             }
248         };
249 
250         WorkerThread workerThread = new WorkerThread(runnable);
251         workerThread.start();
252 
253         try {
254             Thread.sleep(1000);
255         } catch (Exception e) {
256             Log.e(TAG, e.getMessage());
257         }
258 
259         verify(mMockDownloadListener).onDownloadError(
260                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_MEMORY_FULL, 0);
261         workerThread.exit();
262     }
263 
264     @Test
testDownloadFailureConnectionError()265     public void testDownloadFailureConnectionError() {
266         PersistableBundle config = new PersistableBundle();
267         config.putInt(CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 1);
268         config.putInt(CarrierConfigManager.KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 2);
269         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
270         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
271         doNothing().when(mMockDownloadListener).onDownloadError(
272                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
273 
274         Runnable runnable = new Runnable() {
275             @Override
276             public void run() {
277                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
278                 doReturn(false).when(mMockSubInfo).isEmbedded();
279 
280                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
281                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
282                         mMockONSProfileConfig, mMockDownloadListener);
283 
284                 Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
285                 intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
286                 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
287                 intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
288                 intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
289                         ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
290                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE,
291                         EuiccManager.ERROR_CONNECTION_ERROR);
292                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE,
293                         EuiccManager.OPERATION_SMDX);
294 
295                 onsProfileDownloader.onCallbackIntentReceived(intent,
296                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR);
297             }
298         };
299 
300         WorkerThread workerThread = new WorkerThread(runnable);
301         workerThread.start();
302 
303         //After first download error, next download will be triggered between 1 & 2*
304         //CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT(1sec for testing)
305         //Should take less than 2 secs for download re-attempt.
306         try {
307             Thread.sleep(3000);
308         } catch (Exception e) {
309             Log.e(TAG, e.getMessage());
310         }
311 
312         String testActCode = DownloadableSubscription.forActivationCode(TEST_SMDP_ADDRESS)
313                 .getEncodedActivationCode();
314 
315         verify(mMockDownloadListener).onDownloadError(
316                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
317 
318         workerThread.exit();
319     }
320 
321     @Test
testDownloadFailureTimeout()322     public void testDownloadFailureTimeout() {
323         PersistableBundle config = new PersistableBundle();
324         config.putInt(CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 1);
325         config.putInt(CarrierConfigManager.KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 2);
326         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
327         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
328         doNothing().when(mMockDownloadListener).onDownloadError(
329                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
330 
331         Runnable runnable = new Runnable() {
332             @Override
333             public void run() {
334                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
335                 doReturn(false).when(mMockSubInfo).isEmbedded();
336 
337                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
338                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
339                         mMockONSProfileConfig, mMockDownloadListener);
340 
341                 Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
342                 intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
343                 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
344                 intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
345                 intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
346                         ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
347                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE,
348                         EuiccManager.OPERATION_SIM_SLOT);
349                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE,
350                         EuiccManager.ERROR_TIME_OUT);
351 
352                 onsProfileDownloader.onCallbackIntentReceived(intent,
353                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR);
354             }
355         };
356 
357         WorkerThread workerThread = new WorkerThread(runnable);
358         workerThread.start();
359 
360         //After first download error, next download will be triggered between 1 & 2*
361         //CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT(1sec for testing)
362         //Should take less than 2 secs for download re-attempt.
363         try {
364             Thread.sleep(3000);
365         } catch (Exception e) {
366             Log.e(TAG, e.getMessage());
367         }
368 
369         String testActCode = DownloadableSubscription.forActivationCode(TEST_SMDP_ADDRESS)
370                 .getEncodedActivationCode();
371 
372         verify(mMockDownloadListener).onDownloadError(
373                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
374 
375         workerThread.exit();
376     }
377 
378     @Test
testDownloadFailureOperationBusy()379     public void testDownloadFailureOperationBusy() {
380         PersistableBundle config = new PersistableBundle();
381         config.putInt(CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 1);
382         config.putInt(CarrierConfigManager.KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 2);
383         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
384         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
385         doNothing().when(mMockDownloadListener).onDownloadError(
386                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
387 
388         Runnable runnable = new Runnable() {
389             @Override
390             public void run() {
391                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
392                 doReturn(false).when(mMockSubInfo).isEmbedded();
393 
394                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
395                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
396                         mMockONSProfileConfig, mMockDownloadListener);
397 
398                 Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
399                 intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
400                 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
401                 intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
402                 intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
403                         ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
404                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE,
405                         EuiccManager.OPERATION_DOWNLOAD);
406                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE,
407                         EuiccManager.ERROR_OPERATION_BUSY);
408 
409                 onsProfileDownloader.onCallbackIntentReceived(intent,
410                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR);
411             }
412         };
413 
414         WorkerThread workerThread = new WorkerThread(runnable);
415         workerThread.start();
416 
417         //After first download error, next download will be triggered between 1 & 2*
418         //CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT(1sec for testing)
419         //Should take less than 2 secs for download re-attempt.
420         try {
421             Thread.sleep(3000);
422         } catch (Exception e) {
423             Log.e(TAG, e.getMessage());
424         }
425 
426         String testActCode = DownloadableSubscription.forActivationCode(TEST_SMDP_ADDRESS)
427                 .getEncodedActivationCode();
428 
429         verify(mMockDownloadListener).onDownloadError(
430                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
431 
432         workerThread.exit();
433     }
434 
435     @Test
testDownloadFailureInvalidResponse()436     public void testDownloadFailureInvalidResponse() {
437         PersistableBundle config = new PersistableBundle();
438         config.putInt(CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 1);
439         config.putInt(CarrierConfigManager.KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 2);
440         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
441         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
442         doNothing().when(mMockDownloadListener).onDownloadError(
443                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_RETRY_DOWNLOAD, 0);
444 
445         Runnable runnable = new Runnable() {
446             @Override
447             public void run() {
448                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
449                 doReturn(false).when(mMockSubInfo).isEmbedded();
450 
451                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
452                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
453                         mMockONSProfileConfig, mMockDownloadListener);
454 
455                 Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
456                 intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
457                 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
458                 intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
459                 intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
460                         ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
461                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE,
462                         EuiccManager.OPERATION_SMDX);
463                 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE,
464                         EuiccManager.ERROR_INVALID_RESPONSE);
465 
466                 onsProfileDownloader.onCallbackIntentReceived(intent,
467                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR);
468             }
469         };
470 
471         WorkerThread workerThread = new WorkerThread(runnable);
472         workerThread.start();
473 
474         try {
475             Thread.sleep(3000);
476         } catch (Exception e) {
477             e.printStackTrace();
478         }
479 
480         verify(mMockDownloadListener).onDownloadError(
481                 TEST_SUB_ID, ONSProfileDownloader.DownloadRetryResultCode.ERR_UNRESOLVABLE, 0);
482         workerThread.exit();
483     }
484 
485     @Test
testDownloadOpCode()486     public void testDownloadOpCode() {
487         final Object lock = new Object();
488 
489         Runnable runnable = new Runnable() {
490             @Override
491             public void run() {
492                 doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
493                 doReturn(false).when(mMockSubInfo).isEmbedded();
494 
495                 ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mMockContext,
496                         mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
497                         mMockONSProfileConfig, mMockDownloadListener);
498 
499                 ONSProfileDownloader.DownloadHandler downloadHandler =
500                         onsProfileDownloader.new DownloadHandler();
501 
502                 ONSProfileDownloader.DownloadRetryResultCode res =
503                         downloadHandler.mapDownloaderErrorCode(
504                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0, 0, 0);
505                 assertEquals(
506                         ONSProfileDownloader.DownloadRetryResultCode.DOWNLOAD_SUCCESSFUL, res);
507 
508                 res = downloadHandler.mapDownloaderErrorCode(
509                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
510                         EuiccManager.OPERATION_EUICC_GSMA,
511                         EuiccManager.ERROR_EUICC_INSUFFICIENT_MEMORY);
512                 assertEquals(ONSProfileDownloader.DownloadRetryResultCode
513                         .ERR_MEMORY_FULL, res);
514 
515                 res = downloadHandler.mapDownloaderErrorCode(
516                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
517                         EuiccManager.OPERATION_SIM_SLOT,
518                         EuiccManager.ERROR_TIME_OUT);
519                 assertEquals(ONSProfileDownloader.DownloadRetryResultCode
520                         .ERR_RETRY_DOWNLOAD, res);
521 
522                 res = downloadHandler.mapDownloaderErrorCode(
523                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
524                         EuiccManager.OPERATION_SMDX,
525                         EuiccManager.ERROR_CONNECTION_ERROR);
526                 assertEquals(ONSProfileDownloader.DownloadRetryResultCode
527                         .ERR_RETRY_DOWNLOAD, res);
528 
529                 res = downloadHandler.mapDownloaderErrorCode(
530                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR, 0,
531                         EuiccManager.OPERATION_SMDX,
532                         EuiccManager.ERROR_INVALID_RESPONSE);
533                 assertEquals(ONSProfileDownloader.DownloadRetryResultCode
534                         .ERR_UNRESOLVABLE, res);
535 
536                 res = downloadHandler.mapDownloaderErrorCode(
537                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 0,
538                         EuiccManager.OPERATION_SMDX,
539                         EuiccManager.ERROR_INVALID_RESPONSE);
540                 assertEquals(ONSProfileDownloader.DownloadRetryResultCode
541                         .ERR_UNRESOLVABLE, res);
542 
543                 res = downloadHandler.mapDownloaderErrorCode(
544                         EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 0xA810048,
545                         EuiccManager.OPERATION_SMDX_SUBJECT_REASON_CODE, 0);
546                 assertEquals(ONSProfileDownloader.DownloadRetryResultCode
547                         .ERR_MEMORY_FULL, res);
548 
549                 synchronized (lock) {
550                     lock.notifyAll();
551                 }
552             }
553         };
554 
555         WorkerThread workerThread = new WorkerThread(runnable);
556         workerThread.start();
557 
558         synchronized (lock) {
559             try {
560                 lock.wait();
561             } catch (Exception e) {
562                 Log.e(TAG, e.getLocalizedMessage());
563             }
564         }
565 
566         workerThread.exit();
567     }
568 
569     @Test
testSMDPErrorParsing()570     public void testSMDPErrorParsing() {
571         final Object lock = new Object();
572 
573         Runnable runnable = new Runnable() {
574             @Override
575             public void run() {
576                 Pair<String, String> res = ONSProfileDownloader
577                         .decodeSmdxSubjectAndReasonCode(0xA8B1051);
578                 //0A->OPERATION_SMDX_SUBJECT_REASON_CODE
579                 //8B1 -> 8.11.1
580                 //051 -> 5.1
581                 assertEquals("8.11.1", res.first);
582                 assertEquals("5.1", res.second);
583 
584                 res = ONSProfileDownloader
585                         .decodeSmdxSubjectAndReasonCode(0xA810061);
586                 //0A->OPERATION_SMDX_SUBJECT_REASON_CODE
587                 //810 -> 8.1.0
588                 //061 -> 6.1
589                 assertEquals("8.1.0", res.first);
590                 assertEquals("6.1", res.second);
591 
592                 res = ONSProfileDownloader
593                         .decodeSmdxSubjectAndReasonCode(0xA810048);
594                 //0A->OPERATION_SMDX_SUBJECT_REASON_CODE
595                 //810 -> 8.1.0
596                 //048 -> 4.8
597                 assertEquals("8.1.0", res.first);
598                 assertEquals("4.8", res.second);
599 
600                 res = ONSProfileDownloader
601                         .decodeSmdxSubjectAndReasonCode(0xA8B1022);
602                 //0A->OPERATION_SMDX_SUBJECT_REASON_CODE
603                 //8B1 -> 8.11.1
604                 //022 -> 2.2
605                 assertEquals("8.11.1", res.first);
606                 assertEquals("2.2", res.second);
607 
608                 synchronized (lock) {
609                     lock.notifyAll();
610                 }
611             }
612         };
613 
614         WorkerThread workerThread = new WorkerThread(runnable);
615         workerThread.start();
616 
617         synchronized (lock) {
618             try {
619                 lock.wait();
620             } catch (Exception e) {
621                 Log.e(TAG, e.getLocalizedMessage());
622             }
623         }
624 
625         workerThread.exit();
626     }
627 
628     @Test
testMultipleDownloadRequests()629     public void testMultipleDownloadRequests() {
630         doReturn(TEST_SUB_ID).when(mMockSubInfo).getSubscriptionId();
631         PersistableBundle config = new PersistableBundle();
632         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
633         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
634         doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
635         doReturn(false).when(mMockSubInfo).isEmbedded();
636 
637         ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
638                 mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
639                 mMockONSProfileConfig, mMockDownloadListener);
640 
641         //When multiple download requests are received, download should be triggered only once.
642         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
643         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
644         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
645         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
646         verify(mMockEuiccManager, times(1)).downloadSubscription(any(), eq(true), any());
647 
648         //Simulate response for download request from LPA.
649         Intent intent = new Intent(mContext, ONSProfileResultReceiver.class);
650         intent.setAction(ONSProfileDownloader.ACTION_ONS_ESIM_DOWNLOAD);
651         intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ONSProfileDownloader.class.getName());
652         intent.putExtra(ONSProfileDownloader.PARAM_PRIMARY_SUBID, TEST_SUB_ID);
653         intent.putExtra(ONSProfileDownloader.PARAM_REQUEST_TYPE,
654                 ONSProfileDownloader.REQUEST_CODE_DOWNLOAD_SUB);
655         intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE,
656                 EuiccManager.OPERATION_DOWNLOAD);
657 
658         onsProfileDownloader.onCallbackIntentReceived(intent,
659                 EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK);
660 
661         //Trigger new download after a sec
662         try {
663             Thread.sleep(1000);
664         } catch (Exception e) {
665             e.printStackTrace();
666         }
667 
668         //After download response is received, new download requests should be processed.
669         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
670         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
671         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
672         onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
673         verify(mMockEuiccManager, times(1)).downloadSubscription(any(), eq(true), any());
674     }
675 
676     @Test
testDownloadRequestFailures()677     public void testDownloadRequestFailures() {
678         doReturn(TEST_SUB_ID).when(mMockSubInfo).getSubscriptionId();
679         doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
680         doReturn(false).when(mMockSubInfo).isEmbedded();
681 
682         PersistableBundle invalidConfig = new PersistableBundle();
683         invalidConfig.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, "");
684 
685         PersistableBundle validConfig = new PersistableBundle();
686         validConfig.putString(
687                 CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
688 
689         // Only the first download request, will receive invalid SMDP server address.
690         doReturn(invalidConfig, validConfig)
691                 .when(mMockCarrierConfigManager)
692                 .getConfigForSubId(TEST_SUB_ID);
693 
694         ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
695                 mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
696                 mMockONSProfileConfig, mMockDownloadListener);
697 
698         // First download request to be failed with INVALID_SMDP_ADDRESS error because of empty SMDP
699         // server address in configuration.
700         DownloadProfileResult retryResultCode =
701                 onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
702         assertEquals(DownloadProfileResult.INVALID_SMDP_ADDRESS, retryResultCode);
703 
704         verify(mMockEuiccManager, never()).downloadSubscription(any(), eq(true), any());
705 
706         // Second Download request should be success and processed to EuiccManager.
707         retryResultCode = onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
708         assertEquals(DownloadProfileResult.SUCCESS, retryResultCode);
709         verify(mMockEuiccManager).downloadSubscription(any(), eq(true), any());
710 
711         // Since download request is in progress, no further request to be sent to EuiccManager.
712         // They should return with DUPLICATE_REQUEST error.
713         retryResultCode = onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
714         assertEquals(DownloadProfileResult.DUPLICATE_REQUEST, retryResultCode);
715 
716         retryResultCode = onsProfileDownloader.downloadProfile(mMockSubInfo.getSubscriptionId());
717         assertEquals(DownloadProfileResult.DUPLICATE_REQUEST, retryResultCode);
718 
719         verify(mMockEuiccManager).downloadSubscription(any(), eq(true), any());
720     }
721 
722     @Test
testDownloadRequestWithPrimaryESim()723     public void testDownloadRequestWithPrimaryESim() {
724         doReturn(TEST_SUB_ID).when(mMockSubInfo).getSubscriptionId();
725         doReturn(TEST_SUB_ID).when(mMockSubInfo).getCardId();
726         doReturn(true).when(mMockSubInfo).isEmbedded();
727         doReturn(mMockEuiccManagerForCard1).when(mMockEuiccManager)
728                 .createForCardId(TEST_EUICC_CARD_ID);
729         PersistableBundle config = new PersistableBundle();
730         config.putInt(CarrierConfigManager.KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 1);
731         config.putInt(CarrierConfigManager.KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 2);
732         config.putString(CarrierConfigManager.KEY_SMDP_SERVER_ADDRESS_STRING, TEST_SMDP_ADDRESS);
733         doReturn(config).when(mMockCarrierConfigManager).getConfigForSubId(TEST_SUB_ID);
734 
735         // Check null subscription info - eSIM case
736         doReturn(null).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
737         verify(mMockEuiccManagerForCard1, never()).downloadSubscription(any(), eq(true), any());
738 
739         doReturn(mMockSubInfo).when(mMockSubManager).getActiveSubscriptionInfo(TEST_SUB_ID);
740         ONSProfileDownloader onsProfileDownloader = new ONSProfileDownloader(mContext,
741                 mMockCarrierConfigManager, mMockEuiccManager, mMockSubManager,
742                 mMockONSProfileConfig, mMockDownloadListener);
743 
744         onsProfileDownloader.downloadProfile(TEST_SUB_ID);
745         verify(mMockEuiccManagerForCard1, times(1)).downloadSubscription(any(), eq(true), any());
746     }
747 
748     @After
tearDown()749     public void tearDown() throws Exception {
750         super.tearDown();
751     }
752 }
753