• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.provider.cts.simphonebook;
18 
19 import static android.provider.SimPhonebookContract.ElementaryFiles.EF_ADN;
20 
21 import static com.android.internal.telephony.testing.CursorSubject.assertThat;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 import static com.google.common.truth.Truth.assertWithMessage;
25 
26 import android.Manifest;
27 import android.content.ContentResolver;
28 import android.content.ContentValues;
29 import android.content.Context;
30 import android.content.pm.PackageManager;
31 import android.database.Cursor;
32 import android.net.Uri;
33 import android.provider.SimPhonebookContract.ElementaryFiles;
34 import android.provider.SimPhonebookContract.SimRecords;
35 import android.telephony.SubscriptionInfo;
36 import android.telephony.SubscriptionManager;
37 import android.util.SparseBooleanArray;
38 
39 import androidx.annotation.NonNull;
40 import androidx.test.core.app.ApplicationProvider;
41 import androidx.test.ext.junit.runners.AndroidJUnit4;
42 
43 import com.android.compatibility.common.util.RequiredFeatureRule;
44 import com.android.compatibility.common.util.SystemUtil;
45 
46 import org.junit.Assume;
47 import org.junit.Before;
48 import org.junit.Rule;
49 import org.junit.Test;
50 import org.junit.rules.RuleChain;
51 import org.junit.rules.TestRule;
52 import org.junit.runner.RunWith;
53 
54 import java.util.ArrayList;
55 import java.util.List;
56 import java.util.Objects;
57 
58 @RunWith(AndroidJUnit4.class)
59 public class SimPhonebookContract_ElementaryFilesTest {
60 
61     // The minimum value for the ElementaryFiles.NAME_MAX_LENGTH column.
62     private static final int NAME_MAX_LENGTH_MINIMUM = 2;
63     // The minimum value for the ElementaryFiles.PHONE_NUMBER_MAX_LENGTH column.
64     private static final int PHONE_NUMBER_MAX_LENGTH_MINIMUM = 20;
65 
66     private ContentResolver mResolver;
67     private SubscriptionManager mSubscriptionManager;
68     private int mValidSubscriptionId;
69 
70     @Rule
71     public final TestRule mRule = RuleChain
72             .outerRule(new RequiredFeatureRule(PackageManager.FEATURE_TELEPHONY))
73             .around(new SimPhonebookRequirementsRule())
74             .around(new SimsCleanupRule(ElementaryFiles.EF_ADN));
75 
76     @Before
setUp()77     public void setUp() {
78         Context context = ApplicationProvider.getApplicationContext();
79         mResolver = context.getContentResolver();
80         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
81         mValidSubscriptionId = new RemovableSims(context).getDefaultSubscriptionId();
82     }
83 
84     @Test
query_includesRowForEachElementaryFileOnEachSim()85     public void query_includesRowForEachElementaryFileOnEachSim() throws Exception {
86         List<SubscriptionInfo> subscriptionInfos = SystemUtil.callWithShellPermissionIdentity(
87                 () -> mSubscriptionManager.getActiveSubscriptionInfoList(),
88                 Manifest.permission.READ_PHONE_STATE);
89         // FDN and SDN support are more rare and less important than ADN so we allow the test to
90         // work on a SIM where they are unsupported. This does leave a gap in coverage but given
91         // their relatively low importance as compared to ADN and the fact that the implementation
92         // should be very similar for each type it's OK to just assume good faith on the part of the
93         // implementation.
94         SparseBooleanArray fdnSupportedBySubId = new SparseBooleanArray();
95         SparseBooleanArray sdnSupportedBySubId = new SparseBooleanArray();
96         for (SubscriptionInfo info : subscriptionInfos) {
97             int subscriptionId = info.getSubscriptionId();
98             try (Cursor cursor = mResolver.query(
99                     ElementaryFiles.getItemUri(subscriptionId, ElementaryFiles.EF_FDN),
100                     new String[]{ElementaryFiles.SUBSCRIPTION_ID}, null, null)) {
101                 // If the EF is unsupported the item Uri will return an empty cursor
102                 if (Objects.requireNonNull(cursor).moveToFirst()) {
103                     assertWithMessage("subscriptionId")
104                             .that(subscriptionId).isEqualTo(cursor.getInt(0));
105                     fdnSupportedBySubId.append(subscriptionId, true);
106                 }
107             }
108             try (Cursor cursor = mResolver.query(
109                     ElementaryFiles.getItemUri(subscriptionId, ElementaryFiles.EF_SDN),
110                     new String[]{ElementaryFiles.SUBSCRIPTION_ID}, null, null)) {
111                 // If the EF is unsupported the item Uri will return an empty cursor
112                 if (Objects.requireNonNull(cursor).moveToFirst()) {
113                     assertWithMessage("subscriptionId")
114                             .that(subscriptionId).isEqualTo(cursor.getInt(0));
115                     sdnSupportedBySubId.append(subscriptionId, true);
116                 }
117             }
118         }
119 
120         try (Cursor cursor = query(ElementaryFiles.CONTENT_URI,
121                 new String[]{
122                         ElementaryFiles.SLOT_INDEX,
123                         ElementaryFiles.SUBSCRIPTION_ID,
124                         ElementaryFiles.EF_TYPE,
125                         ElementaryFiles.MAX_RECORDS,
126                         ElementaryFiles.NAME_MAX_LENGTH,
127                         ElementaryFiles.PHONE_NUMBER_MAX_LENGTH
128                 })) {
129 
130             assertThat(cursor).hasCount(subscriptionInfos.size() + fdnSupportedBySubId.size()
131                     + sdnSupportedBySubId.size());
132             cursor.moveToPosition(-1);
133             for (SubscriptionInfo info : subscriptionInfos) {
134                 List<Integer> supportedEfs = new ArrayList<>(3);
135                 supportedEfs.add(ElementaryFiles.EF_ADN);
136                 if (fdnSupportedBySubId.get(info.getSubscriptionId())) {
137                     supportedEfs.add(ElementaryFiles.EF_FDN);
138                 }
139                 if (sdnSupportedBySubId.get(info.getSubscriptionId())) {
140                     supportedEfs.add(ElementaryFiles.EF_SDN);
141                 }
142                 for (int efType : supportedEfs) {
143                     assertThat(cursor.moveToNext()).isTrue();
144                     assertThat(cursor)
145                             .hasRowValue(ElementaryFiles.SLOT_INDEX, info.getSimSlotIndex())
146                             .hasRowValue(ElementaryFiles.SUBSCRIPTION_ID, info.getSubscriptionId())
147                             .hasRowValue(ElementaryFiles.EF_TYPE, efType);
148                     assertThat(cursor).intField(ElementaryFiles.MAX_RECORDS).isAtLeast(1);
149                     assertThat(cursor).intField(ElementaryFiles.NAME_MAX_LENGTH)
150                             .isAtLeast(NAME_MAX_LENGTH_MINIMUM);
151                     assertThat(cursor).intField(ElementaryFiles.PHONE_NUMBER_MAX_LENGTH)
152                             .isAtLeast(PHONE_NUMBER_MAX_LENGTH_MINIMUM);
153                 }
154             }
155         }
156     }
157 
158     @Test
query_nonEmptySim_countIsCorrect()159     public void query_nonEmptySim_countIsCorrect() {
160         String[] projection = {
161                 ElementaryFiles.SUBSCRIPTION_ID,
162                 ElementaryFiles.EF_TYPE,
163                 ElementaryFiles.RECORD_COUNT
164         };
165         ContentValues values = new ContentValues();
166         values.put(SimRecords.PHONE_NUMBER, "5550101");
167         Uri itemUri = mResolver.insert(SimRecords.getContentUri(mValidSubscriptionId, EF_ADN),
168                 values);
169         mResolver.insert(SimRecords.getContentUri(mValidSubscriptionId, EF_ADN), values);
170         mResolver.insert(SimRecords.getContentUri(mValidSubscriptionId, EF_ADN), values);
171 
172         try (Cursor adn = query(
173                 ElementaryFiles.getItemUri(mValidSubscriptionId, ElementaryFiles.EF_ADN),
174                 projection)) {
175             assertThat(adn).hasSingleRow(mValidSubscriptionId, ElementaryFiles.EF_ADN, 3);
176         }
177 
178         mResolver.delete(itemUri, null);
179 
180         try (Cursor adn = query(
181                 ElementaryFiles.getItemUri(mValidSubscriptionId, ElementaryFiles.EF_ADN),
182                 projection)) {
183             assertThat(adn).hasSingleRow(mValidSubscriptionId, ElementaryFiles.EF_ADN, 2);
184         }
185     }
186 
187     @Test
query_adnItemUri_returnsCorrectRow()188     public void query_adnItemUri_returnsCorrectRow() {
189         try (Cursor cursor = query(
190                 ElementaryFiles.getItemUri(mValidSubscriptionId, ElementaryFiles.EF_ADN),
191                 new String[]{
192                         ElementaryFiles.SUBSCRIPTION_ID,
193                         ElementaryFiles.EF_TYPE
194                 })) {
195             assertThat(cursor).hasSingleRow(mValidSubscriptionId, ElementaryFiles.EF_ADN);
196         }
197     }
198 
199     @Test
query_fdnItemUri_returnsCorrectRow()200     public void query_fdnItemUri_returnsCorrectRow() {
201         try (Cursor cursor = query(
202                 ElementaryFiles.getItemUri(mValidSubscriptionId, ElementaryFiles.EF_FDN),
203                 new String[]{
204                         ElementaryFiles.SUBSCRIPTION_ID,
205                         ElementaryFiles.EF_TYPE
206                 })) {
207             // Use an assumption so that the tests don't fail if the SIM doesn't support FDN.
208             Assume.assumeTrue("SIM should support EF_FDN but does not.", cursor.moveToFirst());
209             assertThat(cursor).hasSingleRow(mValidSubscriptionId, ElementaryFiles.EF_FDN);
210         }
211     }
212 
213     @Test
query_sdnItemUri_returnsCorrectRow()214     public void query_sdnItemUri_returnsCorrectRow() {
215         try (Cursor cursor = query(
216                 ElementaryFiles.getItemUri(mValidSubscriptionId, ElementaryFiles.EF_SDN),
217                 new String[]{
218                         ElementaryFiles.SUBSCRIPTION_ID,
219                         ElementaryFiles.EF_TYPE
220                 })) {
221             // Use an assumption so that the tests don't fail if the SIM doesn't support SDN.
222             Assume.assumeTrue("SIM should support EF_SDN but does not.", cursor.moveToFirst());
223             assertThat(cursor).hasSingleRow(mValidSubscriptionId, ElementaryFiles.EF_SDN);
224         }
225     }
226 
227     @NonNull
query(Uri uri, String[] projection)228     private Cursor query(Uri uri, String[] projection) {
229         return Objects.requireNonNull(mResolver.query(uri, projection, null, null));
230     }
231 }
232