1/*
2 * Copyright (C) 2018 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 */
16package com.android.internal.telephony.euicc;
17
18import static junit.framework.Assert.assertEquals;
19import static junit.framework.Assert.assertFalse;
20import static junit.framework.Assert.assertTrue;
21
22import static org.mockito.ArgumentMatchers.any;
23import static org.mockito.Mockito.doAnswer;
24import static org.mockito.Mockito.when;
25
26import android.content.Intent;
27import android.content.SharedPreferences;
28import android.preference.PreferenceManager;
29import android.provider.Settings;
30import android.support.test.runner.AndroidJUnit4;
31import android.telephony.TelephonyManager;
32import android.telephony.euicc.EuiccManager;
33
34import com.android.internal.telephony.TelephonyTest;
35import com.android.internal.telephony.uicc.UiccController;
36import com.android.internal.telephony.uicc.UiccSlot;
37
38import org.junit.After;
39import org.junit.Before;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42import org.mockito.Mock;
43import org.mockito.MockitoAnnotations;
44import org.mockito.invocation.InvocationOnMock;
45import org.mockito.stubbing.Answer;
46
47import java.util.concurrent.CountDownLatch;
48import java.util.concurrent.TimeUnit;
49
50@RunWith(AndroidJUnit4.class)
51public class EuiccCardControllerTest extends TelephonyTest {
52    private static final String KEY_LAST_BOOT_COUNT = "last_boot_count";
53
54    private int mBootCount;
55    private int mLastBootCount;
56    private EuiccCardController mEuiccCardController;
57    private SharedPreferences mSp;
58    @Mock
59    private UiccSlot mInactivatedEsimSlot;
60    @Mock
61    private UiccSlot mActivatedEsimSlot;
62    @Mock
63    private UiccSlot mActivatedRemovableSlot;
64    @Mock
65    private EuiccController mEuiccController;
66    @Mock
67    private UiccController mUiccController;
68    private boolean mOtaStarted;
69    private CountDownLatch mOtaLatch;
70
71
72    @Before
73    public void setUp() throws Exception {
74        super.setUp("EuiccCardControllerTest");
75        MockitoAnnotations.initMocks(this);
76        mSp = PreferenceManager.getDefaultSharedPreferences(mContext);
77
78        mLastBootCount = mSp.getInt(KEY_LAST_BOOT_COUNT, -1);
79        mBootCount = Settings.Global.getInt(
80                mContext.getContentResolver(), Settings.Global.BOOT_COUNT, -1);
81        mOtaStarted = false;
82        mOtaLatch = new CountDownLatch(1);
83
84        when(mEuiccController.getOtaStatus()).thenReturn(EuiccManager.EUICC_OTA_SUCCEEDED);
85        doAnswer(new Answer<Void>() {
86                @Override
87                public Void answer(InvocationOnMock invocation) throws Throwable {
88                    mOtaStarted = true;
89                    mOtaLatch.countDown();
90                    return null;
91                }
92        }).when(mEuiccController).startOtaUpdatingIfNecessary();
93        when(mTelephonyManager.switchSlots(any())).thenReturn(true);
94        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
95        when(mActivatedEsimSlot.isEuicc()).thenReturn(true);
96        when(mActivatedEsimSlot.isActive()).thenReturn(true);
97        when(mInactivatedEsimSlot.isEuicc()).thenReturn(true);
98        when(mInactivatedEsimSlot.isActive()).thenReturn(false);
99        when(mActivatedRemovableSlot.isEuicc()).thenReturn(false);
100        when(mActivatedRemovableSlot.isActive()).thenReturn(true);
101    }
102
103    @After
104    public void tearDown() throws Exception {
105        super.tearDown();
106        if (mBootCount == -1) {
107            Settings.Global.resetToDefaults(mContext.getContentResolver(), KEY_LAST_BOOT_COUNT);
108        } else {
109            Settings.Global.putInt(mContext.getContentResolver(),
110                    Settings.Global.BOOT_COUNT, mBootCount);
111        }
112        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
113        sp.edit().putInt(KEY_LAST_BOOT_COUNT, mLastBootCount).apply();
114    }
115
116    @Test
117    public void testIsBootUp() {
118        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
119        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
120        assertTrue(EuiccCardController.isBootUp(mContext));
121
122        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
123        Settings.Global.resetToDefaults(mContext.getContentResolver(), KEY_LAST_BOOT_COUNT);
124        assertTrue(EuiccCardController.isBootUp(mContext));
125
126        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
127        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 1);
128        assertFalse(EuiccCardController.isBootUp(mContext));
129
130        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 2).apply();
131        assertTrue(EuiccCardController.isBootUp(mContext));
132        assertEquals(mSp.getInt(KEY_LAST_BOOT_COUNT, -1), 1);
133    }
134
135    @Test
136    public void testIsEmbeddedSlotActivated() {
137        mEuiccCardController =
138                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
139        when(mUiccController.getUiccSlots())
140                .thenReturn(new UiccSlot[] {mActivatedRemovableSlot});
141        assertFalse(mEuiccCardController.isEmbeddedSlotActivated());
142
143        when(mUiccController.getUiccSlots())
144                .thenReturn(new UiccSlot[] {mActivatedEsimSlot});
145        assertTrue(mEuiccCardController.isEmbeddedSlotActivated());
146
147        when(mUiccController.getUiccSlots())
148                .thenReturn(new UiccSlot[] {mInactivatedEsimSlot});
149        assertFalse(mEuiccCardController.isEmbeddedSlotActivated());
150
151        when(mUiccController.getUiccSlots())
152                .thenReturn(new UiccSlot[] {
153                        mActivatedEsimSlot, mInactivatedEsimSlot, mActivatedRemovableSlot});
154        assertTrue(mEuiccCardController.isEmbeddedSlotActivated());
155
156        when(mUiccController.getUiccSlots())
157                .thenReturn(new UiccSlot[] {
158                        mInactivatedEsimSlot, mActivatedEsimSlot, mActivatedRemovableSlot});
159        assertTrue(mEuiccCardController.isEmbeddedSlotActivated());
160    }
161
162    @Test
163    public void testStartOtaUpdatingIfNecessary_onEmbeddedSlot() {
164        // isBootUp = true
165        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
166        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
167        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});
168
169        mEuiccCardController =
170                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
171        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
172        try {
173            mOtaLatch.await(5000, TimeUnit.MILLISECONDS);
174            assertTrue(mOtaStarted);
175        } catch (InterruptedException ignore) { }
176    }
177
178    @Test
179    public void testStartOtaUpdatingIfNecessary_notBootUp() {
180        // isBootUp = false
181        mSp.edit().putInt(KEY_LAST_BOOT_COUNT, 1).apply();
182        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 1);
183        when(mUiccController.getUiccSlots()).thenReturn(new UiccSlot[] {mActivatedEsimSlot});
184        mEuiccCardController =
185                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
186
187        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
188        assertFalse(mOtaStarted);
189    }
190
191    @Test
192    public void testStartOtaUpdatingIfNecessary_onRemovableSlot() {
193        // isBootUp = true
194        mSp.edit().remove(KEY_LAST_BOOT_COUNT);
195        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.BOOT_COUNT, 0);
196        when(mUiccController.getUiccSlots())
197                .thenReturn(new UiccSlot[] {mActivatedRemovableSlot, mInactivatedEsimSlot});
198
199        mEuiccCardController =
200                new EuiccCardController(mContext, null, mEuiccController, mUiccController);
201        mContext.sendBroadcast(new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
202        assertFalse(mOtaStarted);
203    }
204}
205