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