1 /*
2  * Copyright (C) 2021 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.imsserviceentitlement.utils;
18 
19 import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
20 
21 import android.content.Context;
22 import android.net.ConnectivityManager;
23 import android.net.NetworkInfo;
24 import android.os.PersistableBundle;
25 import android.telephony.CarrierConfigManager;
26 import android.telephony.SubscriptionInfo;
27 import android.telephony.SubscriptionManager;
28 import android.telephony.TelephonyManager;
29 import android.util.Log;
30 
31 import com.google.common.collect.ImmutableSet;
32 
33 import java.util.List;
34 
35 /** This class implements Telephony helper methods. */
36 public class TelephonyUtils {
37     public static final String TAG = "IMSSE-TelephonyUtils";
38     // TODO(b/326358344) : API review for hide carrier configurations
39     private static final String KEY_ENTITLEMENT_VERSION_INT =
40             "imsserviceentitlement.entitlement_version_int";
41     private static final String KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL =
42             "imsserviceentitlement.default_service_entitlement_status_bool";
43 
44     private final ConnectivityManager mConnectivityManager;
45     private final TelephonyManager mTelephonyManager;
46 
TelephonyUtils(Context context)47     public TelephonyUtils(Context context) {
48         this(context, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
49     }
50 
TelephonyUtils(Context context, int subId)51     public TelephonyUtils(Context context, int subId) {
52         if (SubscriptionManager.isValidSubscriptionId(subId)) {
53             mTelephonyManager =
54                     context.getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
55         } else {
56             mTelephonyManager = context.getSystemService(TelephonyManager.class);
57         }
58         mConnectivityManager = context.getSystemService(ConnectivityManager.class);
59     }
60 
61     /** Returns device timestamp in milliseconds. */
getTimeStamp()62     public long getTimeStamp() {
63         return System.currentTimeMillis();
64     }
65 
66     /** Returns device uptime in milliseconds. */
getUptimeMillis()67     public long getUptimeMillis() {
68         return android.os.SystemClock.uptimeMillis();
69     }
70 
71     /** Returns {@code true} if network is connected (cellular or WiFi). */
isNetworkConnected()72     public boolean isNetworkConnected() {
73         NetworkInfo activeNetwork = mConnectivityManager.getActiveNetworkInfo();
74         return activeNetwork != null && activeNetwork.isConnected();
75     }
76 
77     /** Returns carrier ID. */
getCarrierId()78     public int getCarrierId() {
79         return mTelephonyManager.getSimCarrierId();
80     }
81 
82     /** Returns fine-grained carrier ID. */
getSpecificCarrierId()83     public int getSpecificCarrierId() {
84         return mTelephonyManager.getSimSpecificCarrierId();
85     }
86 
87     /** Returns SIM card application state. */
getSimApplicationState()88     public int getSimApplicationState() {
89         return mTelephonyManager.getSimApplicationState();
90     }
91 
92     /**
93      * Returns {@code true} if the {@code subId} still point to a actived SIM; {@code false}
94      * otherwise.
95      */
isActivedSubId(Context context, int subId)96     public static boolean isActivedSubId(Context context, int subId) {
97         SubscriptionManager subscriptionManager =
98                 (SubscriptionManager) context.getSystemService(
99                         Context.TELEPHONY_SUBSCRIPTION_SERVICE);
100         SubscriptionInfo subInfo = subscriptionManager.getActiveSubscriptionInfo(subId);
101         return subInfo != null;
102     }
103 
104     /**
105      * Returns the slot index for the actived {@code subId}; {@link
106      * SubscriptionManager#INVALID_SIM_SLOT_INDEX} otherwise.
107      */
getSlotId(Context context, int subId)108     public static int getSlotId(Context context, int subId) {
109         SubscriptionManager subscriptionManager =
110                 (SubscriptionManager) context.getSystemService(
111                         Context.TELEPHONY_SUBSCRIPTION_SERVICE);
112         SubscriptionInfo subInfo = subscriptionManager.getActiveSubscriptionInfo(subId);
113         if (subInfo != null) {
114             return subInfo.getSimSlotIndex();
115         }
116         Log.d(TAG, "Can't find actived subscription for " + subId);
117         return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
118     }
119 
120     /** Returns carrier config for the {@code subId}. */
getConfigForSubId(Context context, int subId)121     private static PersistableBundle getConfigForSubId(Context context, int subId) {
122         CarrierConfigManager carrierConfigManager =
123                 context.getSystemService(CarrierConfigManager.class);
124         PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId);
125         if (carrierConfig == null) {
126             Log.d(TAG, "getDefaultConfig");
127             carrierConfig = CarrierConfigManager.getDefaultConfig();
128         }
129         return carrierConfig;
130     }
131 
132     /**
133      * Returns FCM sender id for the {@code subId} or a default empty string if it is not available.
134      */
getFcmSenderId(Context context, int subId)135     public static String getFcmSenderId(Context context, int subId) {
136         return getConfigForSubId(context, subId).getString(
137                 CarrierConfigManager.ImsServiceEntitlement.KEY_FCM_SENDER_ID_STRING,
138                 ""
139         );
140     }
141 
142     /**
143      * Returns entitlement server url for the {@code subId} or
144      * a default empty string if it is not available.
145      */
getEntitlementServerUrl(Context context, int subId)146     public static String getEntitlementServerUrl(Context context, int subId) {
147         return getConfigForSubId(context, subId).getString(
148                 CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING,
149                 ""
150         );
151     }
152 
153     /**
154      * Returns true if app needs to do IMS (VoLTE/VoNR/VoWiFi/SMSoIP) provisioning in the background
155      * or false if it doesn't need to do.
156      */
isImsProvisioningRequired(Context context, int subId)157     public static boolean isImsProvisioningRequired(Context context, int subId) {
158         return getConfigForSubId(context, subId).getBoolean(
159                 CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL,
160                 false
161         );
162     }
163 
164     /**
165      * Returns entitlement version for the {@code subId} or {@link
166      * Ts43Constants.ENTITLEMENT_VERSION_TWO} if it is not available.
167      */
getEntitlementVersion(Context context, int subId)168     public static int getEntitlementVersion(Context context, int subId) {
169         return getConfigForSubId(context, subId).getInt(
170                 KEY_ENTITLEMENT_VERSION_INT,
171                 ENTITLEMENT_VERSION_TWO
172         );
173     }
174 
175     /**
176      * Returns default service entitlement status for the {@code subId} or false if it is not
177      * available.
178      */
getDefaultStatus(Context context, int subId)179     public static boolean getDefaultStatus(Context context, int subId) {
180         return getConfigForSubId(context, subId).getBoolean(
181                 KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL,
182                 false
183         );
184     }
185 
186     /** Returns SubIds which support FCM. */
getSubIdsWithFcmSupported(Context context)187     public static ImmutableSet<Integer> getSubIdsWithFcmSupported(Context context) {
188         SubscriptionManager subscriptionManager =
189                 context.getSystemService(SubscriptionManager.class);
190         List<SubscriptionInfo> infos = subscriptionManager.getActiveSubscriptionInfoList();
191         if (infos == null) {
192             return ImmutableSet.of();
193         }
194 
195         ImmutableSet.Builder<Integer> builder = ImmutableSet.builder();
196         for (SubscriptionInfo info : infos) {
197             int subId = info.getSubscriptionId();
198             if (isFcmPushNotificationSupported(context, subId)) {
199                 builder.add(subId);
200             }
201         }
202         return builder.build();
203     }
204 
isFcmPushNotificationSupported(Context context, int subId)205     private static boolean isFcmPushNotificationSupported(Context context, int subId) {
206         return !TelephonyUtils.getFcmSenderId(context, subId).isEmpty();
207     }
208 }
209