• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.telephony.ims.cts;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.PackageManager;
22 import android.content.pm.ResolveInfo;
23 import android.os.Binder;
24 import android.service.carrier.CarrierService;
25 import android.telephony.SubscriptionInfo;
26 import android.telephony.SubscriptionManager;
27 import android.telephony.TelephonyManager;
28 import android.util.Log;
29 
30 import androidx.test.platform.app.InstrumentationRegistry;
31 
32 import com.android.compatibility.common.util.ShellIdentityUtils;
33 
34 import java.io.ByteArrayInputStream;
35 import java.io.ByteArrayOutputStream;
36 import java.io.IOException;
37 import java.util.List;
38 import java.util.concurrent.Callable;
39 import java.util.zip.GZIPInputStream;
40 import java.util.zip.GZIPOutputStream;
41 
42 public class ImsUtils {
43     public static final boolean VDBG = true;
44 
45     // ImsService rebind has an exponential backoff capping at 64 seconds. Wait for 70 seconds to
46     // allow for the new poll to happen in the framework.
47     public static final int TEST_TIMEOUT_MS = 70000;
48 
49     // Id for non compressed auto configuration xml.
50     public static final int ITEM_NON_COMPRESSED = 2000;
51     // Id for compressed auto configuration xml.
52     public static final int ITEM_COMPRESSED = 2001;
53 
54     private static final String TAG = "ImsUtils";
55 
shouldTestTelephony()56     public static boolean shouldTestTelephony() {
57         final PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
58                 .getPackageManager();
59         return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
60     }
61 
shouldTestImsService()62     public static boolean shouldTestImsService() {
63         final PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
64                 .getPackageManager();
65         boolean hasTelephony = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
66         boolean hasIms = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS);
67         return hasTelephony && hasIms;
68     }
69 
shouldTestImsCall()70     public static boolean shouldTestImsCall() {
71         final PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
72                 .getPackageManager();
73         return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)
74                 && pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING);
75     }
76 
shouldTestImsSingleRegistration()77     public static boolean shouldTestImsSingleRegistration() {
78         final PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
79                 .getPackageManager();
80         boolean hasTelephony = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
81         boolean hasSingleReg = pm.hasSystemFeature(
82                 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
83         return hasTelephony && hasSingleReg;
84     }
85 
getPreferredActiveSubId()86     public static int getPreferredActiveSubId() {
87         Context context = InstrumentationRegistry.getInstrumentation().getContext();
88         SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
89                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
90         List<SubscriptionInfo> infos = ShellIdentityUtils.invokeMethodWithShellPermissions(sm,
91                 SubscriptionManager::getActiveSubscriptionInfoList);
92 
93         int defaultSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
94         if (defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
95                 && isSubIdInInfoList(infos, defaultSubId)) {
96             return defaultSubId;
97         }
98 
99         defaultSubId = SubscriptionManager.getDefaultSubscriptionId();
100         if (defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
101                 && isSubIdInInfoList(infos, defaultSubId)) {
102             return defaultSubId;
103         }
104 
105         // Couldn't resolve a default. We can try to resolve a default using the active
106         // subscriptions.
107         if (!infos.isEmpty()) {
108             return infos.get(0).getSubscriptionId();
109         }
110         // There must be at least one active subscription.
111         return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
112     }
113 
isSubIdInInfoList(List<SubscriptionInfo> infos, int subId)114     private static boolean isSubIdInInfoList(List<SubscriptionInfo> infos, int subId) {
115         return infos.stream().anyMatch(info -> info.getSubscriptionId() == subId);
116     }
117 
118     /**
119      * If a carrier app implements CarrierMessagingService it can choose to take care of handling
120      * SMS OTT so SMS over IMS APIs won't be triggered which would be WAI so we do not run the tests
121      * if there exist a carrier app that declares a CarrierMessagingService
122      */
shouldRunSmsImsTests(int subId)123     public static boolean shouldRunSmsImsTests(int subId) {
124         if (!shouldTestImsService()) {
125             return false;
126         }
127         Context context = InstrumentationRegistry.getInstrumentation().getContext();
128         TelephonyManager tm =
129                 (TelephonyManager) InstrumentationRegistry.getInstrumentation().getContext()
130                         .getSystemService(Context.TELEPHONY_SERVICE);
131         tm = tm.createForSubscriptionId(subId);
132         final long token = Binder.clearCallingIdentity();
133         List<String> carrierPackages;
134         try {
135             carrierPackages = ShellIdentityUtils.invokeMethodWithShellPermissions(tm,
136                     (m) -> m.getCarrierPackageNamesForIntent(
137                             new Intent(CarrierService.CARRIER_SERVICE_INTERFACE)));
138         } finally {
139             Binder.restoreCallingIdentity(token);
140         }
141 
142         final PackageManager packageManager = context.getPackageManager();
143         Intent intent = new Intent("android.service.carrier.CarrierMessagingService");
144         List<ResolveInfo> resolveInfos = packageManager.queryIntentServices(intent, 0);
145         boolean detected = resolveInfos != null && !resolveInfos.isEmpty();
146         Log.i(TAG, "resolveInfos are detected: " + detected);
147 
148         boolean exist = carrierPackages != null && !carrierPackages.isEmpty();
149         Log.i(TAG, "carrierPackages exist: " + exist);
150 
151         if (!exist) {
152             return true;
153         }
154 
155         for (ResolveInfo info : resolveInfos) {
156             if (carrierPackages.contains(info.serviceInfo.packageName)) {
157                 return false;
158             }
159         }
160 
161         return true;
162     }
163 
164     /**
165      * Retry every 5 seconds until the condition is true or fail after TEST_TIMEOUT_MS seconds.
166      */
retryUntilTrue(Callable<Boolean> condition)167     public static boolean retryUntilTrue(Callable<Boolean> condition) throws Exception {
168         return retryUntilTrue(condition, TEST_TIMEOUT_MS, 14 /*numTries*/);
169     }
170 
171     /**
172      * Retry every timeoutMs/numTimes until the condition is true or fail if the condition is never
173      * met.
174      */
retryUntilTrue(Callable<Boolean> condition, int timeoutMs, int numTimes)175     public static boolean retryUntilTrue(Callable<Boolean> condition,
176             int timeoutMs, int numTimes) throws Exception {
177         int sleepTime = timeoutMs / numTimes;
178         int retryCounter = 0;
179         while (retryCounter < numTimes) {
180             try {
181                 Boolean isSuccessful = condition.call();
182                 isSuccessful = (isSuccessful == null) ? false : isSuccessful;
183                 if (isSuccessful) return true;
184             } catch (Exception e) {
185                 // we will retry
186             }
187             Thread.sleep(sleepTime);
188             retryCounter++;
189         }
190         return false;
191     }
192 
193     /**
194      * compress the gzip format data
195      * @hide
196      */
compressGzip(byte[] data)197     public static byte[] compressGzip(byte[] data) {
198         if (data == null || data.length == 0) {
199             return data;
200         }
201         byte[] out = null;
202         try {
203             ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
204             GZIPOutputStream gzipCompressingStream =
205                     new GZIPOutputStream(outputStream);
206             gzipCompressingStream.write(data);
207             gzipCompressingStream.close();
208             out = outputStream.toByteArray();
209             outputStream.close();
210         } catch (IOException e) {
211         }
212         return out;
213     }
214 
215     /**
216      * decompress the gzip format data
217      * @hide
218      */
decompressGzip(byte[] data)219     public static byte[] decompressGzip(byte[] data) {
220         if (data == null || data.length == 0) {
221             return data;
222         }
223         byte[] out = null;
224         try {
225             ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
226             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
227             GZIPInputStream gzipDecompressingStream =
228                     new GZIPInputStream(inputStream);
229             byte[] buf = new byte[1024];
230             int size = gzipDecompressingStream.read(buf);
231             while (size >= 0) {
232                 outputStream.write(buf, 0, size);
233                 size = gzipDecompressingStream.read(buf);
234             }
235             gzipDecompressingStream.close();
236             inputStream.close();
237             out = outputStream.toByteArray();
238             outputStream.close();
239         } catch (IOException e) {
240         }
241         return out;
242     }
243 }
244