1 /* //device/content/providers/telephony/TelephonyProvider.java 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 package com.android.providers.telephony; 19 20 import static android.provider.Telephony.Carriers.ALWAYS_ON; 21 import static android.provider.Telephony.Carriers.APN; 22 import static android.provider.Telephony.Carriers.APN_SET_ID; 23 import static android.provider.Telephony.Carriers.AUTH_TYPE; 24 import static android.provider.Telephony.Carriers.BEARER; 25 import static android.provider.Telephony.Carriers.BEARER_BITMASK; 26 import static android.provider.Telephony.Carriers.CARRIER_DELETED; 27 import static android.provider.Telephony.Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML; 28 import static android.provider.Telephony.Carriers.CARRIER_EDITED; 29 import static android.provider.Telephony.Carriers.CARRIER_ENABLED; 30 import static android.provider.Telephony.Carriers.CARRIER_ID; 31 import static android.provider.Telephony.Carriers.CONTENT_URI; 32 import static android.provider.Telephony.Carriers.CURRENT; 33 import static android.provider.Telephony.Carriers.DEFAULT_SORT_ORDER; 34 import static android.provider.Telephony.Carriers.EDITED_STATUS; 35 import static android.provider.Telephony.Carriers.INFRASTRUCTURE_BITMASK; 36 import static android.provider.Telephony.Carriers.ESIM_BOOTSTRAP_PROVISIONING; 37 import static android.provider.Telephony.Carriers.LINGERING_NETWORK_TYPE_BITMASK; 38 import static android.provider.Telephony.Carriers.MAX_CONNECTIONS; 39 import static android.provider.Telephony.Carriers.MCC; 40 import static android.provider.Telephony.Carriers.MMSC; 41 import static android.provider.Telephony.Carriers.MMSPORT; 42 import static android.provider.Telephony.Carriers.MMSPROXY; 43 import static android.provider.Telephony.Carriers.MNC; 44 import static android.provider.Telephony.Carriers.MODEM_PERSIST; 45 import static android.provider.Telephony.Carriers.MTU; 46 import static android.provider.Telephony.Carriers.MTU_V4; 47 import static android.provider.Telephony.Carriers.MTU_V6; 48 import static android.provider.Telephony.Carriers.MVNO_MATCH_DATA; 49 import static android.provider.Telephony.Carriers.MVNO_TYPE; 50 import static android.provider.Telephony.Carriers.NAME; 51 import static android.provider.Telephony.Carriers.NETWORK_TYPE_BITMASK; 52 import static android.provider.Telephony.Carriers.NO_APN_SET_ID; 53 import static android.provider.Telephony.Carriers.NUMERIC; 54 import static android.provider.Telephony.Carriers.OWNED_BY; 55 import static android.provider.Telephony.Carriers.OWNED_BY_DPC; 56 import static android.provider.Telephony.Carriers.OWNED_BY_OTHERS; 57 import static android.provider.Telephony.Carriers.PASSWORD; 58 import static android.provider.Telephony.Carriers.PORT; 59 import static android.provider.Telephony.Carriers.PROFILE_ID; 60 import static android.provider.Telephony.Carriers.PROTOCOL; 61 import static android.provider.Telephony.Carriers.PROXY; 62 import static android.provider.Telephony.Carriers.ROAMING_PROTOCOL; 63 import static android.provider.Telephony.Carriers.SERVER; 64 import static android.provider.Telephony.Carriers.SKIP_464XLAT; 65 import static android.provider.Telephony.Carriers.SKIP_464XLAT_DEFAULT; 66 import static android.provider.Telephony.Carriers.SUBSCRIPTION_ID; 67 import static android.provider.Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS; 68 import static android.provider.Telephony.Carriers.TYPE; 69 import static android.provider.Telephony.Carriers.UNEDITED; 70 import static android.provider.Telephony.Carriers.USER; 71 import static android.provider.Telephony.Carriers.USER_DELETED; 72 import static android.provider.Telephony.Carriers.USER_DELETED_BUT_PRESENT_IN_XML; 73 import static android.provider.Telephony.Carriers.USER_EDITABLE; 74 import static android.provider.Telephony.Carriers.USER_EDITED; 75 import static android.provider.Telephony.Carriers.USER_VISIBLE; 76 import static android.provider.Telephony.Carriers.WAIT_TIME_RETRY; 77 import static android.provider.Telephony.Carriers._ID; 78 79 import android.annotation.NonNull; 80 import android.annotation.Nullable; 81 import android.app.compat.CompatChanges; 82 import android.content.ComponentName; 83 import android.content.ContentProvider; 84 import android.content.ContentResolver; 85 import android.content.ContentUris; 86 import android.content.ContentValues; 87 import android.content.Context; 88 import android.content.Intent; 89 import android.content.ServiceConnection; 90 import android.content.SharedPreferences; 91 import android.content.UriMatcher; 92 import android.content.pm.PackageManager; 93 import android.content.res.Resources; 94 import android.content.res.XmlResourceParser; 95 import android.database.Cursor; 96 import android.database.MatrixCursor; 97 import android.database.SQLException; 98 import android.database.sqlite.SQLiteDatabase; 99 import android.database.sqlite.SQLiteException; 100 import android.database.sqlite.SQLiteOpenHelper; 101 import android.database.sqlite.SQLiteQueryBuilder; 102 import android.net.Uri; 103 import android.os.Binder; 104 import android.os.Bundle; 105 import android.os.Environment; 106 import android.os.IBinder; 107 import android.os.PersistableBundle; 108 import android.os.Process; 109 import android.os.RemoteException; 110 import android.os.SystemProperties; 111 import android.os.UserHandle; 112 import android.provider.Telephony; 113 import android.service.carrier.IApnSourceService; 114 import android.telephony.SubscriptionInfo; 115 import android.telephony.SubscriptionManager; 116 import android.telephony.TelephonyManager; 117 import android.telephony.TelephonyProtoEnums; 118 import android.telephony.data.ApnSetting; 119 import android.text.TextUtils; 120 import android.util.ArrayMap; 121 import android.util.ArraySet; 122 import android.util.AtomicFile; 123 import android.util.IndentingPrintWriter; 124 import android.util.LocalLog; 125 import android.util.Log; 126 import android.util.Pair; 127 import android.util.Xml; 128 129 import com.android.internal.annotations.GuardedBy; 130 import com.android.internal.annotations.VisibleForTesting; 131 import com.android.internal.telephony.TelephonyPermissions; 132 import com.android.internal.telephony.TelephonyStatsLog; 133 import com.android.internal.telephony.flags.Flags; 134 import com.android.internal.util.XmlUtils; 135 136 import org.xmlpull.v1.XmlPullParser; 137 import org.xmlpull.v1.XmlPullParserException; 138 139 import java.io.ByteArrayOutputStream; 140 import java.io.File; 141 import java.io.FileDescriptor; 142 import java.io.FileInputStream; 143 import java.io.FileNotFoundException; 144 import java.io.FileOutputStream; 145 import java.io.FileReader; 146 import java.io.IOException; 147 import java.io.InputStream; 148 import java.io.PrintWriter; 149 import java.util.ArrayList; 150 import java.util.Arrays; 151 import java.util.HashMap; 152 import java.util.HashSet; 153 import java.util.List; 154 import java.util.Locale; 155 import java.util.Map; 156 import java.util.Set; 157 import java.util.concurrent.atomic.AtomicBoolean; 158 import java.util.stream.Collectors; 159 import java.util.zip.CRC32; 160 import java.util.zip.CheckedInputStream; 161 162 public class TelephonyProvider extends ContentProvider 163 { 164 private static final String DATABASE_NAME = "telephony.db"; 165 private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000; 166 private static final boolean DBG = true; 167 private static final boolean VDBG = false; // STOPSHIP if true 168 169 private static final int DATABASE_VERSION = 74 << 16; 170 private static final int URL_UNKNOWN = 0; 171 private static final int URL_TELEPHONY = 1; 172 private static final int URL_CURRENT = 2; 173 private static final int URL_ID = 3; 174 private static final int URL_RESTOREAPN = 4; 175 private static final int URL_PREFERAPN = 5; 176 private static final int URL_PREFERAPN_NO_UPDATE = 6; 177 private static final int URL_SIMINFO = 7; 178 private static final int URL_TELEPHONY_USING_SUBID = 8; 179 private static final int URL_CURRENT_USING_SUBID = 9; 180 private static final int URL_RESTOREAPN_USING_SUBID = 10; 181 private static final int URL_PREFERAPN_USING_SUBID = 11; 182 private static final int URL_PREFERAPN_NO_UPDATE_USING_SUBID = 12; 183 private static final int URL_SIMINFO_USING_SUBID = 13; 184 private static final int URL_UPDATE_DB = 14; 185 private static final int URL_DELETE = 15; 186 private static final int URL_DPC = 16; 187 private static final int URL_DPC_ID = 17; 188 private static final int URL_FILTERED = 18; 189 private static final int URL_FILTERED_ID = 19; 190 private static final int URL_ENFORCE_MANAGED = 20; 191 // URL_PREFERAPNSET and URL_PREFERAPNSET_USING_SUBID return all APNs for the current 192 // carrier which have an apn_set_id equal to the preferred APN 193 // (if no preferred APN, or preferred APN has no set id, the query will return null) 194 private static final int URL_PREFERAPNSET = 21; 195 private static final int URL_PREFERAPNSET_USING_SUBID = 22; 196 private static final int URL_SIM_APN_LIST = 23; 197 private static final int URL_SIM_APN_LIST_ID = 24; 198 private static final int URL_FILTERED_USING_SUBID = 25; 199 private static final int URL_SIM_APN_LIST_FILTERED = 26; 200 private static final int URL_SIM_APN_LIST_FILTERED_ID = 27; 201 private static final int URL_SIMINFO_SUW_RESTORE = 28; 202 private static final int URL_SIMINFO_SIM_INSERTED_RESTORE = 29; 203 204 private static final String TAG = "TelephonyProvider"; 205 private static final String CARRIERS_TABLE = "carriers"; 206 private static final String CARRIERS_TABLE_TMP = "carriers_tmp"; 207 private static final String SIMINFO_TABLE = "siminfo"; 208 private static final String SIMINFO_TABLE_TMP = "siminfo_tmp"; 209 210 private static final String PREF_FILE_APN = "preferred-apn"; 211 private static final String COLUMN_APN_ID = "apn_id"; 212 private static final String EXPLICIT_SET_CALLED = "explicit_set_called"; 213 214 private static final String PREF_FILE_FULL_APN = "preferred-full-apn"; 215 private static final String DB_VERSION_KEY = "version"; 216 217 private static final String BUILD_ID_FILE = "build-id"; 218 private static final String RO_BUILD_ID = "ro_build_id"; 219 220 private static final String ENFORCED_FILE = "dpc-apn-enforced"; 221 private static final String ENFORCED_KEY = "enforced"; 222 223 private static final String PREF_FILE = "telephonyprovider"; 224 private static final String APN_CONF_CHECKSUM = "apn_conf_checksum"; 225 226 private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml"; 227 private static final String OEM_APNS_PATH = "telephony/apns-conf.xml"; 228 private static final String OTA_UPDATED_APNS_PATH = "misc/apns/apns-conf.xml"; 229 private static final String OLD_APNS_PATH = "etc/old-apns-conf.xml"; 230 231 private static final String DEFAULT_PROTOCOL = "IP"; 232 private static final String DEFAULT_ROAMING_PROTOCOL = "IP"; 233 234 private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH); 235 236 private static final ContentValues s_currentNullMap; 237 private static final ContentValues s_currentSetMap; 238 239 private static final String IS_UNEDITED = EDITED_STATUS + "=" + UNEDITED; 240 private static final String IS_EDITED = EDITED_STATUS + "!=" + UNEDITED; 241 private static final String IS_USER_EDITED = EDITED_STATUS + "=" + USER_EDITED; 242 private static final String IS_NOT_USER_EDITED = EDITED_STATUS + "!=" + USER_EDITED; 243 private static final String IS_USER_DELETED = EDITED_STATUS + "=" + USER_DELETED; 244 private static final String IS_NOT_USER_DELETED = EDITED_STATUS + "!=" + USER_DELETED; 245 private static final String IS_USER_DELETED_BUT_PRESENT_IN_XML = 246 EDITED_STATUS + "=" + USER_DELETED_BUT_PRESENT_IN_XML; 247 private static final String IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML = 248 EDITED_STATUS + "!=" + USER_DELETED_BUT_PRESENT_IN_XML; 249 private static final String IS_CARRIER_EDITED = EDITED_STATUS + "=" + CARRIER_EDITED; 250 private static final String IS_NOT_CARRIER_EDITED = EDITED_STATUS + "!=" + CARRIER_EDITED; 251 private static final String IS_CARRIER_DELETED = EDITED_STATUS + "=" + CARRIER_DELETED; 252 private static final String IS_NOT_CARRIER_DELETED = EDITED_STATUS + "!=" + CARRIER_DELETED; 253 private static final String IS_CARRIER_DELETED_BUT_PRESENT_IN_XML = 254 EDITED_STATUS + "=" + CARRIER_DELETED_BUT_PRESENT_IN_XML; 255 private static final String IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML = 256 EDITED_STATUS + "!=" + CARRIER_DELETED_BUT_PRESENT_IN_XML; 257 private static final String IS_OWNED_BY_DPC = OWNED_BY + "=" + OWNED_BY_DPC; 258 private static final String IS_NOT_OWNED_BY_DPC = OWNED_BY + "!=" + OWNED_BY_DPC; 259 260 private static final String ORDER_BY_SUB_ID = 261 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + " ASC"; 262 263 @VisibleForTesting 264 static final String BACKED_UP_SIM_SPECIFIC_SETTINGS_FILE = "sim_specific_settings_file"; 265 // Holds names and value types of SimInfoDb columns to backup. 266 private static final Map<String, Integer> SIM_INFO_COLUMNS_TO_BACKUP = new HashMap(); 267 private static final String KEY_SIMINFO_DB_ROW_PREFIX = "KEY_SIMINFO_DB_ROW_"; 268 private static final int DEFAULT_INT_COLUMN_VALUE = -111; 269 private static final String DEFAULT_STRING_COLUMN_VALUE = "DEFAULT_STRING_COLUMN_VALUE"; 270 private static final String SIM_INSERTED_RESTORE_URI_SUFFIX = "sim_inserted_restore"; 271 @VisibleForTesting 272 static final String KEY_BACKUP_DATA_FORMAT_VERSION = "KEY_BACKUP_DATA_FORMAT_VERSION"; 273 @VisibleForTesting 274 static final String KEY_PREVIOUSLY_RESTORED_SUB_IDS = "KEY_PREVIOUSLY_RESTORED_SUB_IDS"; 275 276 private static final int INVALID_APN_ID = -1; 277 private static final List<String> CARRIERS_UNIQUE_FIELDS = new ArrayList<String>(); 278 private static final Set<String> CARRIERS_BOOLEAN_FIELDS = new HashSet<String>(); 279 private static final Map<String, String> CARRIERS_UNIQUE_FIELDS_DEFAULTS = new HashMap(); 280 private static final String ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G = "enable_2g"; 281 282 @VisibleForTesting 283 static Boolean s_apnSourceServiceExists; 284 285 protected final Object mLock = new Object(); 286 @GuardedBy("mLock") 287 private IApnSourceService mIApnSourceService; 288 private Injector mInjector; 289 290 private boolean mManagedApnEnforced; 291 292 /** 293 * Lazy tracking SubscriptionManager#getDefaultSubscriptionId for db operation to prevent race 294 * condition. 295 * Make sure the call is outside of instance synchronization to prevent dead lock between 296 * SubscriptionManager lock and telephony provider lock. 297 */ 298 private int mDefaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 299 300 private final LocalLog mLocalLog = new LocalLog(128); 301 302 /** 303 * Mobile country codes where there is a high likelyhood that the MNC has 3 digits 304 * and need one more prefix zero to set correct mobile network code value. 305 * 306 * Please note! The best solution is to add the MCCMNC combo to carrier id 307 * carrier_list, this is just a best effort. 308 */ 309 private static final String[] COUNTRY_MCC_WITH_THREE_DIGIT_MNC = { 310 "302" // Canada 311 ,"310" // Guam, USA 312 ,"311" // USA 313 ,"312" // USA 314 ,"313" // USA 315 ,"316" // USA 316 ,"334" // Mexico 317 ,"338" // Bermuda, Jamaica 318 ,"342" // Barbados 319 ,"344" // Antigua and Barbuda 320 ,"346" // Cayman Islands 321 ,"348" // British Virgin Islands 322 ,"356" // Saint Kitts and Nevis 323 ,"358" // Saint Lucia 324 ,"360" // Saint Vincent and the Grenadines 325 ,"365" // Anguilla 326 ,"366" // Dominica 327 ,"376" // Turks and Caicos Islands 328 ,"405" // India 329 ,"708" // Honduras 330 ,"722" // Argentina 331 ,"732" // Colombia 332 ,"738" // Guyana 333 ,"750" // Falkland Islands 334 }; 335 336 /** 337 * Available radio technologies for GSM, UMTS and CDMA. 338 * Duplicates the constants from hardware/radio/include/ril.h 339 * This should only be used by agents working with the ril. Others 340 * should use the equivalent TelephonyManager.NETWORK_TYPE_* 341 */ 342 private static final int RIL_RADIO_TECHNOLOGY_UNKNOWN = 0; 343 private static final int RIL_RADIO_TECHNOLOGY_GPRS = 1; 344 private static final int RIL_RADIO_TECHNOLOGY_EDGE = 2; 345 private static final int RIL_RADIO_TECHNOLOGY_UMTS = 3; 346 private static final int RIL_RADIO_TECHNOLOGY_IS95A = 4; 347 private static final int RIL_RADIO_TECHNOLOGY_IS95B = 5; 348 private static final int RIL_RADIO_TECHNOLOGY_1xRTT = 6; 349 private static final int RIL_RADIO_TECHNOLOGY_EVDO_0 = 7; 350 private static final int RIL_RADIO_TECHNOLOGY_EVDO_A = 8; 351 private static final int RIL_RADIO_TECHNOLOGY_HSDPA = 9; 352 private static final int RIL_RADIO_TECHNOLOGY_HSUPA = 10; 353 private static final int RIL_RADIO_TECHNOLOGY_HSPA = 11; 354 private static final int RIL_RADIO_TECHNOLOGY_EVDO_B = 12; 355 private static final int RIL_RADIO_TECHNOLOGY_EHRPD = 13; 356 private static final int RIL_RADIO_TECHNOLOGY_LTE = 14; 357 private static final int RIL_RADIO_TECHNOLOGY_HSPAP = 15; 358 359 /** 360 * GSM radio technology only supports voice. It does not support data. 361 */ 362 private static final int RIL_RADIO_TECHNOLOGY_GSM = 16; 363 private static final int RIL_RADIO_TECHNOLOGY_TD_SCDMA = 17; 364 365 /** 366 * IWLAN 367 */ 368 private static final int RIL_RADIO_TECHNOLOGY_IWLAN = 18; 369 370 /** 371 * LTE_CA 372 */ 373 private static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19; 374 375 /** 376 * NR(New Radio) 5G. 377 */ 378 private static final int RIL_RADIO_TECHNOLOGY_NR = 20; 379 380 /** 381 * The number of the radio technologies. 382 */ 383 private static final int NEXT_RIL_RADIO_TECHNOLOGY = 21; 384 385 private static final Map<String, Integer> MVNO_TYPE_STRING_MAP; 386 387 static { 388 // Columns not included in UNIQUE constraint: name, current, edited, user, server, password, 389 // authtype, type, protocol, roaming_protocol, sub_id, modem_cognitive, max_conns, 390 // wait_time, max_conns_time, mtu, mtu_v4, mtu_v6, bearer_bitmask, user_visible, 391 // network_type_bitmask, skip_464xlat, lingering_network_type_bitmask, always_on. CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(NUMERIC, "")392 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(NUMERIC, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MCC, "")393 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MCC, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MNC, "")394 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MNC, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN, "")395 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROXY, "")396 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROXY, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PORT, "")397 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PORT, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPROXY, "")398 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPROXY, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPORT, "")399 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPORT, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSC, "")400 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSC, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(CARRIER_ENABLED, "1")401 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(CARRIER_ENABLED, "1"); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(BEARER, "0")402 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(BEARER, "0"); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_TYPE, "")403 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_TYPE, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_MATCH_DATA, "")404 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_MATCH_DATA, ""); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROFILE_ID, "0")405 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROFILE_ID, "0"); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROTOCOL, "IP")406 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROTOCOL, "IP"); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(ROAMING_PROTOCOL, "IP")407 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(ROAMING_PROTOCOL, "IP"); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(USER_EDITABLE, "1")408 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(USER_EDITABLE, "1"); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(OWNED_BY, String.valueOf(OWNED_BY_OTHERS))409 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(OWNED_BY, String.valueOf(OWNED_BY_OTHERS)); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN_SET_ID, String.valueOf(NO_APN_SET_ID))410 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN_SET_ID, String.valueOf(NO_APN_SET_ID)); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(CARRIER_ID, String.valueOf(TelephonyManager.UNKNOWN_CARRIER_ID))411 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(CARRIER_ID, 412 String.valueOf(TelephonyManager.UNKNOWN_CARRIER_ID)); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(INFRASTRUCTURE_BITMASK, String.valueOf( ApnSetting.INFRASTRUCTURE_CELLULAR | ApnSetting.INFRASTRUCTURE_SATELLITE))413 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(INFRASTRUCTURE_BITMASK, 414 String.valueOf( 415 ApnSetting.INFRASTRUCTURE_CELLULAR | ApnSetting.INFRASTRUCTURE_SATELLITE)); CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(ESIM_BOOTSTRAP_PROVISIONING, "0")416 CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(ESIM_BOOTSTRAP_PROVISIONING, "0"); 417 CARRIERS_UNIQUE_FIELDS_DEFAULTS.keySet()418 CARRIERS_UNIQUE_FIELDS.addAll(CARRIERS_UNIQUE_FIELDS_DEFAULTS.keySet()); 419 420 // SQLite databases store bools as ints but the ContentValues objects passed in through 421 // queries use bools. As a result there is some special handling of boolean fields within 422 // the TelephonyProvider. 423 CARRIERS_BOOLEAN_FIELDS.add(CARRIER_ENABLED); 424 CARRIERS_BOOLEAN_FIELDS.add(MODEM_PERSIST); 425 CARRIERS_BOOLEAN_FIELDS.add(USER_VISIBLE); 426 CARRIERS_BOOLEAN_FIELDS.add(USER_EDITABLE); 427 CARRIERS_BOOLEAN_FIELDS.add(ESIM_BOOTSTRAP_PROVISIONING); 428 429 MVNO_TYPE_STRING_MAP = new ArrayMap<>(); 430 MVNO_TYPE_STRING_MAP.put("spn", ApnSetting.MVNO_TYPE_SPN); 431 MVNO_TYPE_STRING_MAP.put("imsi", ApnSetting.MVNO_TYPE_IMSI); 432 MVNO_TYPE_STRING_MAP.put("gid", ApnSetting.MVNO_TYPE_GID); 433 MVNO_TYPE_STRING_MAP.put("iccid", ApnSetting.MVNO_TYPE_ICCID); 434 435 // To B&R a new config, simply add the column name and its appropriate value type to 436 // SIM_INFO_COLUMNS_TO_BACKUP. To no longer B&R a column, simply remove it from 437 // SIM_INFO_COLUMNS_TO_BACKUP. For both cases, add appropriate versioning logic in 438 // convertBackedUpDataToContentValues(ContentValues contenValues) SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, Cursor.FIELD_TYPE_INTEGER)439 SIM_INFO_COLUMNS_TO_BACKUP.put( 440 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_ICC_ID, Cursor.FIELD_TYPE_STRING)441 SIM_INFO_COLUMNS_TO_BACKUP.put( 442 Telephony.SimInfo.COLUMN_ICC_ID, Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_NUMBER, Cursor.FIELD_TYPE_STRING)443 SIM_INFO_COLUMNS_TO_BACKUP.put( 444 Telephony.SimInfo.COLUMN_NUMBER, Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_CARRIER_ID, Cursor.FIELD_TYPE_INTEGER)445 SIM_INFO_COLUMNS_TO_BACKUP.put( 446 Telephony.SimInfo.COLUMN_CARRIER_ID, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, Cursor.FIELD_TYPE_INTEGER)447 SIM_INFO_COLUMNS_TO_BACKUP.put( 448 Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, Cursor.FIELD_TYPE_INTEGER)449 SIM_INFO_COLUMNS_TO_BACKUP.put( 450 Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_VT_IMS_ENABLED, Cursor.FIELD_TYPE_INTEGER)451 SIM_INFO_COLUMNS_TO_BACKUP.put( 452 Telephony.SimInfo.COLUMN_VT_IMS_ENABLED, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING, Cursor.FIELD_TYPE_INTEGER)453 SIM_INFO_COLUMNS_TO_BACKUP.put( 454 Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, Cursor.FIELD_TYPE_STRING)455 SIM_INFO_COLUMNS_TO_BACKUP.put( 456 Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 457 Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, Cursor.FIELD_TYPE_INTEGER)458 SIM_INFO_COLUMNS_TO_BACKUP.put( 459 Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_WFC_IMS_MODE, Cursor.FIELD_TYPE_INTEGER)460 SIM_INFO_COLUMNS_TO_BACKUP.put( 461 Telephony.SimInfo.COLUMN_WFC_IMS_MODE, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, Cursor.FIELD_TYPE_INTEGER)462 SIM_INFO_COLUMNS_TO_BACKUP.put( 463 Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, Cursor.FIELD_TYPE_INTEGER)464 SIM_INFO_COLUMNS_TO_BACKUP.put( 465 Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_USAGE_SETTING, Cursor.FIELD_TYPE_INTEGER)466 SIM_INFO_COLUMNS_TO_BACKUP.put( 467 Telephony.SimInfo.COLUMN_USAGE_SETTING, 468 Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, Cursor.FIELD_TYPE_STRING)469 SIM_INFO_COLUMNS_TO_BACKUP.put( 470 Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENABLED, Cursor.FIELD_TYPE_INTEGER)471 SIM_INFO_COLUMNS_TO_BACKUP.put( 472 Telephony.SimInfo.COLUMN_SATELLITE_ENABLED, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, Cursor.FIELD_TYPE_INTEGER)473 SIM_INFO_COLUMNS_TO_BACKUP.put( 474 Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 475 Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_IS_ONLY_NTN, Cursor.FIELD_TYPE_INTEGER)476 SIM_INFO_COLUMNS_TO_BACKUP.put( 477 Telephony.SimInfo.COLUMN_IS_ONLY_NTN, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_TRANSFER_STATUS, Cursor.FIELD_TYPE_INTEGER)478 SIM_INFO_COLUMNS_TO_BACKUP.put( 479 Telephony.SimInfo.COLUMN_TRANSFER_STATUS, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, Cursor.FIELD_TYPE_INTEGER)480 SIM_INFO_COLUMNS_TO_BACKUP.put( 481 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS, Cursor.FIELD_TYPE_STRING)482 SIM_INFO_COLUMNS_TO_BACKUP.put( 483 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS, 484 Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, Cursor.FIELD_TYPE_STRING)485 SIM_INFO_COLUMNS_TO_BACKUP.put( 486 Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 487 Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED, Cursor.FIELD_TYPE_INTEGER)488 SIM_INFO_COLUMNS_TO_BACKUP.put( 489 Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED, Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM, Cursor.FIELD_TYPE_INTEGER)490 SIM_INFO_COLUMNS_TO_BACKUP.put( 491 Telephony.SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM, 492 Cursor.FIELD_TYPE_INTEGER); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS, Cursor.FIELD_TYPE_STRING)493 SIM_INFO_COLUMNS_TO_BACKUP.put( 494 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS, 495 Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS, Cursor.FIELD_TYPE_STRING)496 SIM_INFO_COLUMNS_TO_BACKUP.put( 497 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS, 498 Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP, Cursor.FIELD_TYPE_STRING)499 SIM_INFO_COLUMNS_TO_BACKUP.put( 500 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP, 501 Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY, Cursor.FIELD_TYPE_STRING)502 SIM_INFO_COLUMNS_TO_BACKUP.put( 503 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY, 504 Cursor.FIELD_TYPE_STRING); SIM_INFO_COLUMNS_TO_BACKUP.put( Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY, Cursor.FIELD_TYPE_STRING)505 SIM_INFO_COLUMNS_TO_BACKUP.put( 506 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY, 507 Cursor.FIELD_TYPE_STRING); 508 } 509 510 @VisibleForTesting getStringForCarrierTableCreation(String tableName)511 public static String getStringForCarrierTableCreation(String tableName) { 512 return "CREATE TABLE " + tableName + 513 "(_id INTEGER PRIMARY KEY," + 514 NAME + " TEXT DEFAULT ''," + 515 NUMERIC + " TEXT DEFAULT ''," + 516 MCC + " TEXT DEFAULT ''," + 517 MNC + " TEXT DEFAULT ''," + 518 CARRIER_ID + " INTEGER DEFAULT " + TelephonyManager.UNKNOWN_CARRIER_ID + "," + 519 APN + " TEXT DEFAULT ''," + 520 USER + " TEXT DEFAULT ''," + 521 SERVER + " TEXT DEFAULT ''," + 522 PASSWORD + " TEXT DEFAULT ''," + 523 PROXY + " TEXT DEFAULT ''," + 524 PORT + " TEXT DEFAULT ''," + 525 MMSPROXY + " TEXT DEFAULT ''," + 526 MMSPORT + " TEXT DEFAULT ''," + 527 MMSC + " TEXT DEFAULT ''," + 528 AUTH_TYPE + " INTEGER DEFAULT -1," + 529 TYPE + " TEXT DEFAULT ''," + 530 CURRENT + " INTEGER," + 531 PROTOCOL + " TEXT DEFAULT " + DEFAULT_PROTOCOL + "," + 532 ROAMING_PROTOCOL + " TEXT DEFAULT " + DEFAULT_ROAMING_PROTOCOL + "," + 533 CARRIER_ENABLED + " BOOLEAN DEFAULT 1," + // SQLite databases store bools as ints 534 BEARER + " INTEGER DEFAULT 0," + 535 BEARER_BITMASK + " INTEGER DEFAULT 0," + 536 NETWORK_TYPE_BITMASK + " INTEGER DEFAULT 0," + 537 LINGERING_NETWORK_TYPE_BITMASK + " INTEGER DEFAULT 0," + 538 MVNO_TYPE + " TEXT DEFAULT ''," + 539 MVNO_MATCH_DATA + " TEXT DEFAULT ''," + 540 SUBSCRIPTION_ID + " INTEGER DEFAULT " + 541 SubscriptionManager.INVALID_SUBSCRIPTION_ID + "," + 542 PROFILE_ID + " INTEGER DEFAULT 0," + 543 MODEM_PERSIST + " BOOLEAN DEFAULT 0," + 544 MAX_CONNECTIONS + " INTEGER DEFAULT 0," + 545 WAIT_TIME_RETRY + " INTEGER DEFAULT 0," + 546 TIME_LIMIT_FOR_MAX_CONNECTIONS + " INTEGER DEFAULT 0," + 547 MTU + " INTEGER DEFAULT 0," + 548 MTU_V4 + " INTEGER DEFAULT 0," + 549 MTU_V6 + " INTEGER DEFAULT 0," + 550 EDITED_STATUS + " INTEGER DEFAULT " + UNEDITED + "," + 551 USER_VISIBLE + " BOOLEAN DEFAULT 1," + 552 USER_EDITABLE + " BOOLEAN DEFAULT 1," + 553 OWNED_BY + " INTEGER DEFAULT " + OWNED_BY_OTHERS + "," + 554 APN_SET_ID + " INTEGER DEFAULT " + NO_APN_SET_ID + "," + 555 SKIP_464XLAT + " INTEGER DEFAULT " + SKIP_464XLAT_DEFAULT + "," + 556 ALWAYS_ON + " INTEGER DEFAULT 0," + 557 INFRASTRUCTURE_BITMASK + " INTEGER DEFAULT 3," + 558 ESIM_BOOTSTRAP_PROVISIONING + " BOOLEAN DEFAULT 0," + 559 // Uniqueness collisions are used to trigger merge code so if a field is listed 560 // here it means we will accept both (user edited + new apn_conf definition) 561 // Columns not included in UNIQUE constraint: name, current, edited, 562 // user, server, password, authtype, type, sub_id, modem_cognitive, max_conns, 563 // wait_time, max_conns_time, mtu, mtu_v4, mtu_v6, bearer_bitmask, user_visible, 564 // network_type_bitmask, skip_464xlat, lingering_network_type_bitmask, always_on. 565 "UNIQUE (" + TextUtils.join(", ", CARRIERS_UNIQUE_FIELDS) + "));"; 566 } 567 568 @VisibleForTesting getStringForSimInfoTableCreation(String tableName)569 public static String getStringForSimInfoTableCreation(String tableName) { 570 return "CREATE TABLE " + tableName + "(" 571 + Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID 572 + " INTEGER PRIMARY KEY AUTOINCREMENT," 573 + Telephony.SimInfo.COLUMN_ICC_ID + " TEXT NOT NULL," 574 + Telephony.SimInfo.COLUMN_SIM_SLOT_INDEX 575 + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_NOT_INSERTED + "," 576 + Telephony.SimInfo.COLUMN_DISPLAY_NAME + " TEXT," 577 + Telephony.SimInfo.COLUMN_CARRIER_NAME + " TEXT," 578 + Telephony.SimInfo.COLUMN_NAME_SOURCE 579 + " INTEGER DEFAULT " + Telephony.SimInfo.NAME_SOURCE_CARRIER_ID + "," 580 + Telephony.SimInfo.COLUMN_COLOR + " INTEGER DEFAULT " 581 + Telephony.SimInfo.COLOR_DEFAULT + "," 582 + Telephony.SimInfo.COLUMN_NUMBER + " TEXT," 583 + Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT 584 + " INTEGER NOT NULL DEFAULT " + Telephony.SimInfo.DISPLAY_NUMBER_DEFAULT + "," 585 + Telephony.SimInfo.COLUMN_DATA_ROAMING 586 + " INTEGER DEFAULT " + Telephony.SimInfo.DATA_ROAMING_DISABLE + "," 587 + Telephony.SimInfo.COLUMN_MCC + " INTEGER DEFAULT 0," 588 + Telephony.SimInfo.COLUMN_MNC + " INTEGER DEFAULT 0," 589 + Telephony.SimInfo.COLUMN_MCC_STRING + " TEXT," 590 + Telephony.SimInfo.COLUMN_MNC_STRING + " TEXT," 591 + Telephony.SimInfo.COLUMN_EHPLMNS + " TEXT," 592 + Telephony.SimInfo.COLUMN_HPLMNS + " TEXT," 593 + Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS 594 + " INTEGER DEFAULT " + Telephony.SimInfo.SIM_PROVISIONED + "," 595 + Telephony.SimInfo.COLUMN_IS_EMBEDDED + " INTEGER DEFAULT 0," 596 + Telephony.SimInfo.COLUMN_CARD_ID + " TEXT NOT NULL," 597 + Telephony.SimInfo.COLUMN_ACCESS_RULES + " BLOB," 598 + Telephony.SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB," 599 + Telephony.SimInfo.COLUMN_IS_REMOVABLE + " INTEGER DEFAULT 0," 600 + Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1," 601 + Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1," 602 + Telephony.SimInfo.COLUMN_CB_AMBER_ALERT + " INTEGER DEFAULT 1," 603 + Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1," 604 + Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4," 605 + Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0," 606 + Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE + " INTEGER DEFAULT 1," 607 + Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH + " INTEGER DEFAULT 1," 608 + Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0," 609 + Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1," 610 + Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0," 611 + Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1," 612 + Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED + " INTEGER DEFAULT -1," 613 + Telephony.SimInfo.COLUMN_VT_IMS_ENABLED + " INTEGER DEFAULT -1," 614 + Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED + " INTEGER DEFAULT -1," 615 + Telephony.SimInfo.COLUMN_WFC_IMS_MODE + " INTEGER DEFAULT -1," 616 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1," 617 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1," 618 + Telephony.SimInfo.COLUMN_IS_OPPORTUNISTIC + " INTEGER DEFAULT 0," 619 + Telephony.SimInfo.COLUMN_GROUP_UUID + " TEXT," 620 + Telephony.SimInfo.COLUMN_IS_METERED + " INTEGER DEFAULT 1," 621 + Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE + " TEXT," 622 + Telephony.SimInfo.COLUMN_CARRIER_ID + " INTEGER DEFAULT -1," 623 + Telephony.SimInfo.COLUMN_PROFILE_CLASS + " INTEGER DEFAULT " 624 + Telephony.SimInfo.PROFILE_CLASS_UNSET + "," 625 + Telephony.SimInfo.COLUMN_SUBSCRIPTION_TYPE + " INTEGER DEFAULT " 626 + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + "," 627 + Telephony.SimInfo.COLUMN_GROUP_OWNER + " TEXT," 628 + Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES + " TEXT," 629 + Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES + " TEXT," 630 + Telephony.SimInfo.COLUMN_IMSI + " TEXT," 631 + Telephony.SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED + " INTEGER DEFAULT 1," 632 + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES + " BIGINT DEFAULT -1," 633 + Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED + " INTEGER DEFAULT 0," 634 + Telephony.SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED + " INTEGER DEFAULT 0," 635 + Telephony.SimInfo.COLUMN_RCS_CONFIG + " BLOB," 636 + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS + " TEXT," 637 + Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING + " INTEGER DEFAULT 0," 638 + Telephony.SimInfo.COLUMN_VOIMS_OPT_IN_STATUS + " INTEGER DEFAULT 0," 639 + Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS + " TEXT," 640 + Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED + " INTEGER DEFAULT -1," 641 + Telephony.SimInfo.COLUMN_PHONE_NUMBER_SOURCE_CARRIER + " TEXT," 642 + Telephony.SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS + " TEXT," 643 + Telephony.SimInfo.COLUMN_PORT_INDEX + " INTEGER DEFAULT -1," 644 + Telephony.SimInfo.COLUMN_USAGE_SETTING + " INTEGER DEFAULT " 645 + SubscriptionManager.USAGE_SETTING_UNKNOWN + "," 646 + Telephony.SimInfo.COLUMN_TP_MESSAGE_REF + 647 " INTEGER DEFAULT -1," 648 + Telephony.SimInfo.COLUMN_USER_HANDLE + " INTEGER DEFAULT " 649 + UserHandle.USER_NULL + "," 650 + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + " INTEGER DEFAULT 0," 651 + Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER 652 + " INTEGER DEFAULT 1, " 653 + Telephony.SimInfo.COLUMN_IS_ONLY_NTN + " INTEGER DEFAULT 0, " 654 + Telephony.SimInfo.COLUMN_SERVICE_CAPABILITIES + " INTEGER DEFAULT " 655 + SubscriptionManager.getAllServiceCapabilityBitmasks() + "," 656 + Telephony.SimInfo.COLUMN_TRANSFER_STATUS + " INTEGER DEFAULT 0," 657 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS + " INTEGER DEFAULT 0," 658 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS + " TEXT," 659 + Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED + " INTEGER DEFAULT 0," 660 + Telephony.SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM 661 + " INTEGER DEFAULT 0," 662 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS + " TEXT," 663 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS + " TEXT," 664 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP + " TEXT," 665 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY + " TEXT," 666 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY + " TEXT" 667 + ");"; 668 } 669 670 static { 671 s_urlMatcher.addURI("telephony", "carriers", URL_TELEPHONY); 672 s_urlMatcher.addURI("telephony", "carriers/current", URL_CURRENT); 673 s_urlMatcher.addURI("telephony", "carriers/#", URL_ID); 674 s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN); 675 s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN); 676 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE); 677 s_urlMatcher.addURI("telephony", "carriers/preferapnset", URL_PREFERAPNSET); 678 679 s_urlMatcher.addURI("telephony", "siminfo", URL_SIMINFO); 680 s_urlMatcher.addURI("telephony", "siminfo/#", URL_SIMINFO_USING_SUBID); 681 s_urlMatcher.addURI("telephony", "siminfo/backup_and_restore/suw_restore", 682 URL_SIMINFO_SUW_RESTORE); 683 s_urlMatcher.addURI("telephony", "siminfo/backup_and_restore/" + 684 SIM_INSERTED_RESTORE_URI_SUFFIX, 685 URL_SIMINFO_SIM_INSERTED_RESTORE); 686 687 s_urlMatcher.addURI("telephony", "carriers/subId/*", URL_TELEPHONY_USING_SUBID); 688 s_urlMatcher.addURI("telephony", "carriers/current/subId/*", URL_CURRENT_USING_SUBID); 689 s_urlMatcher.addURI("telephony", "carriers/restore/subId/*", URL_RESTOREAPN_USING_SUBID); 690 s_urlMatcher.addURI("telephony", "carriers/preferapn/subId/*", URL_PREFERAPN_USING_SUBID); 691 s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update/subId/*", 692 URL_PREFERAPN_NO_UPDATE_USING_SUBID); 693 s_urlMatcher.addURI("telephony", "carriers/preferapnset/subId/*", 694 URL_PREFERAPNSET_USING_SUBID); 695 696 s_urlMatcher.addURI("telephony", "carriers/update_db", URL_UPDATE_DB); 697 s_urlMatcher.addURI("telephony", "carriers/delete", URL_DELETE); 698 699 // Only called by DevicePolicyManager to manipulate DPC records. 700 s_urlMatcher.addURI("telephony", "carriers/dpc", URL_DPC); 701 // Only called by DevicePolicyManager to manipulate a DPC record with certain _ID. 702 s_urlMatcher.addURI("telephony", "carriers/dpc/#", URL_DPC_ID); 703 // Only called by Settings app, DcTracker and other telephony components to get APN list 704 // according to whether DPC records are enforced. 705 s_urlMatcher.addURI("telephony", "carriers/filtered", URL_FILTERED); 706 // Only called by Settings app, DcTracker and other telephony components to get a 707 // single APN according to whether DPC records are enforced. 708 s_urlMatcher.addURI("telephony", "carriers/filtered/#", URL_FILTERED_ID); 709 // Used by DcTracker to pass a subId. 710 s_urlMatcher.addURI("telephony", "carriers/filtered/subId/*", URL_FILTERED_USING_SUBID); 711 712 // Only Called by DevicePolicyManager to enforce DPC records. 713 s_urlMatcher.addURI("telephony", "carriers/enforce_managed", URL_ENFORCE_MANAGED); 714 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list", URL_SIM_APN_LIST); 715 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list/#", URL_SIM_APN_LIST_ID); 716 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list/filtered", 717 URL_SIM_APN_LIST_FILTERED); 718 s_urlMatcher.addURI("telephony", "carriers/sim_apn_list/filtered/subId/*", 719 URL_SIM_APN_LIST_FILTERED_ID); 720 721 s_currentNullMap = new ContentValues(1); s_currentNullMap.put(CURRENT, "0")722 s_currentNullMap.put(CURRENT, "0"); 723 724 s_currentSetMap = new ContentValues(1); s_currentSetMap.put(CURRENT, "1")725 s_currentSetMap.put(CURRENT, "1"); 726 } 727 728 /** 729 * Unit test will subclass it to inject mocks. 730 */ 731 @VisibleForTesting 732 static class Injector { binderGetCallingUid()733 int binderGetCallingUid() { 734 return Binder.getCallingUid(); 735 } 736 } 737 TelephonyProvider()738 public TelephonyProvider() { 739 this(new Injector()); 740 } 741 742 @VisibleForTesting TelephonyProvider(Injector injector)743 public TelephonyProvider(Injector injector) { 744 mInjector = injector; 745 } 746 747 @VisibleForTesting getVersion(Context context)748 public static int getVersion(Context context) { 749 if (VDBG) log("getVersion:+"); 750 // Get the database version, combining a static schema version and the XML version 751 Resources r = context.getResources(); 752 if (r == null) { 753 loge("resources=null, return version=" + Integer.toHexString(DATABASE_VERSION)); 754 return DATABASE_VERSION; 755 } 756 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns); 757 758 if (parser == null) { 759 loge("Null parser"); 760 return DATABASE_VERSION; 761 } 762 763 try { 764 XmlUtils.beginDocument(parser, "apns"); 765 int publicversion = Integer.parseInt(parser.getAttributeValue(null, "version")); 766 int version = DATABASE_VERSION | publicversion; 767 if (VDBG) log("getVersion:- version=0x" + Integer.toHexString(version)); 768 return version; 769 } catch (Exception e) { 770 loge("Can't get version of APN database" + e + " return version=" + 771 Integer.toHexString(DATABASE_VERSION)); 772 return DATABASE_VERSION; 773 } finally { 774 parser.close(); 775 } 776 } 777 778 779 /** 780 * Put the default subscription Id into the provided convent values. 781 * @param values The content values to populate. 782 * @return The populated content values. 783 */ setDefaultValue(ContentValues values)784 public ContentValues setDefaultValue(ContentValues values) { 785 if (!values.containsKey(SUBSCRIPTION_ID)) { 786 values.put(SUBSCRIPTION_ID, mDefaultSubId); 787 } 788 789 return values; 790 } 791 792 @VisibleForTesting 793 public class DatabaseHelper extends SQLiteOpenHelper { 794 // Context to access resources with 795 private Context mContext; 796 797 /** 798 * DatabaseHelper helper class for loading apns into a database. 799 * 800 * @param context of the user. 801 */ DatabaseHelper(Context context)802 public DatabaseHelper(Context context) { 803 super(context, DATABASE_NAME, null, getVersion(context)); 804 mContext = context; 805 // Memory optimization - close idle connections after 30s of inactivity 806 setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS); 807 setWriteAheadLoggingEnabled(false); 808 } 809 810 @Override onCreate(SQLiteDatabase db)811 public void onCreate(SQLiteDatabase db) { 812 if (DBG) log("dbh.onCreate:+ db=" + db); 813 createSimInfoTable(db, SIMINFO_TABLE); 814 createCarriersTable(db, CARRIERS_TABLE); 815 // if CarrierSettings app is installed, we expect it to do the initializiation instead 816 if (apnSourceServiceExists(mContext)) { 817 log("dbh.onCreate: Skipping apply APNs from xml."); 818 } else { 819 log("dbh.onCreate: Apply apns from xml."); 820 initDatabase(db); 821 // Notify listeners of DB change since DB has been updated 822 mContext.getContentResolver().notifyChange( 823 CONTENT_URI, null, true, UserHandle.USER_ALL); 824 } 825 if (DBG) log("dbh.onCreate:- db=" + db); 826 } 827 828 @Override onOpen(SQLiteDatabase db)829 public void onOpen(SQLiteDatabase db) { 830 if (VDBG) log("dbh.onOpen:+ db=" + db); 831 try { 832 // Try to access the table and create it if "no such table" 833 db.query(SIMINFO_TABLE, null, null, null, null, null, null); 834 if (DBG) log("dbh.onOpen: ok, queried table=" + SIMINFO_TABLE); 835 } catch (SQLiteException e) { 836 loge("Exception " + SIMINFO_TABLE + "e=" + e); 837 if (e.getMessage().startsWith("no such table")) { 838 createSimInfoTable(db, SIMINFO_TABLE); 839 } 840 } 841 try { 842 db.query(CARRIERS_TABLE, null, null, null, null, null, null); 843 if (DBG) log("dbh.onOpen: ok, queried table=" + CARRIERS_TABLE); 844 } catch (SQLiteException e) { 845 loge("Exception " + CARRIERS_TABLE + " e=" + e); 846 if (e.getMessage().startsWith("no such table")) { 847 createCarriersTable(db, CARRIERS_TABLE); 848 } 849 } 850 if (VDBG) log("dbh.onOpen:- db=" + db); 851 } 852 createSimInfoTable(SQLiteDatabase db, String tableName)853 private void createSimInfoTable(SQLiteDatabase db, String tableName) { 854 if (DBG) log("dbh.createSimInfoTable:+ " + tableName); 855 db.execSQL(getStringForSimInfoTableCreation(tableName)); 856 if (DBG) log("dbh.createSimInfoTable:-"); 857 } 858 createCarriersTable(SQLiteDatabase db, String tableName)859 private void createCarriersTable(SQLiteDatabase db, String tableName) { 860 // Set up the database schema 861 if (DBG) log("dbh.createCarriersTable: " + tableName); 862 db.execSQL(getStringForCarrierTableCreation(tableName)); 863 if (DBG) log("dbh.createCarriersTable:-"); 864 } 865 getChecksum(File file)866 private long getChecksum(File file) { 867 CRC32 checkSummer = new CRC32(); 868 long checkSum = -1; 869 try (CheckedInputStream cis = 870 new CheckedInputStream(new FileInputStream(file), checkSummer)){ 871 byte[] buf = new byte[128]; 872 if(cis != null) { 873 while(cis.read(buf) >= 0) { 874 // Just read for checksum to get calculated. 875 } 876 } 877 checkSum = checkSummer.getValue(); 878 if (DBG) log("Checksum for " + file.getAbsolutePath() + " is " + checkSum); 879 } catch (FileNotFoundException e) { 880 loge("FileNotFoundException for " + file.getAbsolutePath() + ":" + e); 881 } catch (IOException e) { 882 loge("IOException for " + file.getAbsolutePath() + ":" + e); 883 } 884 885 // The RRO may have been updated in a firmware upgrade. Add checksum for the 886 // resources to the total checksum so that apns in an RRO update is not missed. 887 try (InputStream inputStream = mContext.getResources(). 888 openRawResource(com.android.internal.R.xml.apns)) { 889 byte[] array = toByteArray(inputStream); 890 checkSummer.reset(); 891 checkSummer.update(array); 892 checkSum += checkSummer.getValue(); 893 if (DBG) log("Checksum after adding resource is " + checkSummer.getValue()); 894 } catch (IOException | Resources.NotFoundException e) { 895 loge("Exception when calculating checksum for internal apn resources: " + e); 896 } 897 return checkSum; 898 } 899 toByteArray(InputStream input)900 private byte[] toByteArray(InputStream input) throws IOException { 901 byte[] buffer = new byte[128]; 902 int bytesRead; 903 ByteArrayOutputStream output = new ByteArrayOutputStream(); 904 while ((bytesRead = input.read(buffer)) != -1) { 905 output.write(buffer, 0, bytesRead); 906 } 907 return output.toByteArray(); 908 } 909 getApnConfChecksum()910 private long getApnConfChecksum() { 911 SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); 912 return sp.getLong(APN_CONF_CHECKSUM, -1); 913 } 914 setApnConfChecksum(long checksum)915 private void setApnConfChecksum(long checksum) { 916 SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE); 917 SharedPreferences.Editor editor = sp.edit(); 918 editor.putLong(APN_CONF_CHECKSUM, checksum); 919 editor.apply(); 920 } 921 getApnConfFile()922 private File getApnConfFile() { 923 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". 924 File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH); 925 File oemConfFile = new File(Environment.getOemDirectory(), OEM_APNS_PATH); 926 File updatedConfFile = new File(Environment.getDataDirectory(), OTA_UPDATED_APNS_PATH); 927 File productConfFile = new File(Environment.getProductDirectory(), PARTNER_APNS_PATH); 928 confFile = pickSecondIfExists(confFile, oemConfFile); 929 confFile = pickSecondIfExists(confFile, productConfFile); 930 confFile = pickSecondIfExists(confFile, updatedConfFile); 931 return confFile; 932 } 933 934 /** 935 * This function computes checksum for the file to be read and compares it against the 936 * last read file. DB needs to be updated only if checksum has changed, or old checksum does 937 * not exist. 938 * @return true if DB should be updated with new conf file, false otherwise 939 */ apnDbUpdateNeeded()940 private boolean apnDbUpdateNeeded() { 941 File confFile = getApnConfFile(); 942 long newChecksum = getChecksum(confFile); 943 long oldChecksum = getApnConfChecksum(); 944 if (DBG) log("newChecksum: " + newChecksum); 945 if (DBG) log("oldChecksum: " + oldChecksum); 946 return newChecksum != oldChecksum; 947 } 948 949 /** 950 * This function adds APNs from xml file(s) to db. The db may or may not be empty to begin 951 * with. 952 */ initDatabase(SQLiteDatabase db)953 private void initDatabase(SQLiteDatabase db) { 954 if (VDBG) log("dbh.initDatabase:+ db=" + db); 955 // Read internal APNS data 956 Resources r = mContext.getResources(); 957 int publicversion = -1; 958 if (r != null) { 959 XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns); 960 try { 961 XmlUtils.beginDocument(parser, "apns"); 962 publicversion = Integer.parseInt(parser.getAttributeValue(null, "version")); 963 loadApns(db, parser, true); 964 } catch (Exception e) { 965 loge("Got exception while loading APN database." + e); 966 } finally { 967 parser.close(); 968 } 969 } else { 970 loge("initDatabase: resources=null"); 971 } 972 973 // Read external APNS data (partner-provided) 974 XmlPullParser confparser = null; 975 File confFile = getApnConfFile(); 976 977 FileReader confreader = null; 978 if (DBG) log("confFile = " + confFile); 979 try { 980 confreader = new FileReader(confFile); 981 confparser = Xml.newPullParser(); 982 confparser.setInput(confreader); 983 XmlUtils.beginDocument(confparser, "apns"); 984 985 // Correctness check. Force internal version and confidential versions to agree 986 int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version")); 987 if (publicversion != confversion) { 988 log("initDatabase: throwing exception due to version mismatch"); 989 throw new IllegalStateException("Internal APNS file version doesn't match " 990 + confFile.getAbsolutePath()); 991 } 992 993 loadApns(db, confparser, false); 994 } catch (FileNotFoundException e) { 995 // It's ok if the file isn't found. It means there isn't a confidential file 996 // Log.e(TAG, "File not found: '" + confFile.getAbsolutePath() + "'"); 997 } catch (Exception e) { 998 loge("initDatabase: Exception while parsing '" + confFile.getAbsolutePath() + "'" + 999 e); 1000 } finally { 1001 // Get rid of user/carrier deleted entries that are not present in apn xml file. 1002 // Those entries have edited value USER_DELETED/CARRIER_DELETED. 1003 if (VDBG) { 1004 log("initDatabase: deleting USER_DELETED and replacing " 1005 + "DELETED_BUT_PRESENT_IN_XML with DELETED"); 1006 } 1007 1008 // Delete USER_DELETED 1009 db.delete(CARRIERS_TABLE, IS_USER_DELETED + " or " + IS_CARRIER_DELETED, null); 1010 1011 // Change USER_DELETED_BUT_PRESENT_IN_XML to USER_DELETED 1012 ContentValues cv = new ContentValues(); 1013 cv.put(EDITED_STATUS, USER_DELETED); 1014 db.update(CARRIERS_TABLE, cv, IS_USER_DELETED_BUT_PRESENT_IN_XML, null); 1015 1016 // Change CARRIER_DELETED_BUT_PRESENT_IN_XML to CARRIER_DELETED 1017 cv = new ContentValues(); 1018 cv.put(EDITED_STATUS, CARRIER_DELETED); 1019 db.update(CARRIERS_TABLE, cv, IS_CARRIER_DELETED_BUT_PRESENT_IN_XML, null); 1020 1021 if (confreader != null) { 1022 try { 1023 confreader.close(); 1024 } catch (IOException e) { 1025 // do nothing 1026 } 1027 } 1028 1029 // Update the stored checksum 1030 setApnConfChecksum(getChecksum(confFile)); 1031 } 1032 if (VDBG) log("dbh.initDatabase:- db=" + db); 1033 1034 } 1035 pickSecondIfExists(File sysApnFile, File altApnFile)1036 private File pickSecondIfExists(File sysApnFile, File altApnFile) { 1037 if (altApnFile.exists()) { 1038 if (DBG) log("Load APNs from " + altApnFile.getPath() + 1039 " instead of " + sysApnFile.getPath()); 1040 return altApnFile; 1041 } else { 1042 if (DBG) log("Load APNs from " + sysApnFile.getPath() + 1043 " instead of " + altApnFile.getPath()); 1044 return sysApnFile; 1045 } 1046 } 1047 1048 @Override onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)1049 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 1050 String msg = "dbh.onDowngrade: TelephonyProvider database downgraded from version " 1051 + oldVersion + " to " + newVersion + ". Some user settings might be lost!"; 1052 loge(msg); 1053 mLocalLog.log(msg); 1054 1055 try { 1056 // Delete the database entirely so it can be rebuilt from scratch. 1057 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE); 1058 db.execSQL("DROP TABLE IF EXISTS " + SIMINFO_TABLE); 1059 onCreate(db); 1060 } catch (SQLiteException e) { 1061 loge("Failed to recreate the table " + CARRIERS_TABLE + " and " + SIMINFO_TABLE 1062 + ". e=" + e); 1063 } 1064 } 1065 1066 @Override onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)1067 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 1068 if (DBG) { 1069 log("dbh.onUpgrade:+ db=" + db + " oldV=" + oldVersion + " newV=" + newVersion); 1070 } 1071 1072 deletePreferredApnId(mContext); 1073 1074 if (oldVersion < (5 << 16 | 6)) { 1075 // 5 << 16 is the Database version and 6 in the xml version. 1076 1077 // This change adds a new authtype column to the database. 1078 // The auth type column can have 4 values: 0 (None), 1 (PAP), 2 (CHAP) 1079 // 3 (PAP or CHAP). To avoid breaking compatibility, with already working 1080 // APNs, the unset value (-1) will be used. If the value is -1. 1081 // the authentication will default to 0 (if no user / password) is specified 1082 // or to 3. Currently, there have been no reported problems with 1083 // pre-configured APNs and hence it is set to -1 for them. Similarly, 1084 // if the user, has added a new APN, we set the authentication type 1085 // to -1. 1086 1087 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1088 " ADD COLUMN authtype INTEGER DEFAULT -1;"); 1089 1090 oldVersion = 5 << 16 | 6; 1091 } 1092 if (oldVersion < (6 << 16 | 6)) { 1093 // Add protcol fields to the APN. The XML file does not change. 1094 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1095 " ADD COLUMN protocol TEXT DEFAULT IP;"); 1096 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1097 " ADD COLUMN roaming_protocol TEXT DEFAULT IP;"); 1098 oldVersion = 6 << 16 | 6; 1099 } 1100 if (oldVersion < (7 << 16 | 6)) { 1101 // Add carrier_enabled, bearer fields to the APN. The XML file does not change. 1102 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1103 " ADD COLUMN carrier_enabled BOOLEAN DEFAULT 1;"); 1104 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1105 " ADD COLUMN bearer INTEGER DEFAULT 0;"); 1106 oldVersion = 7 << 16 | 6; 1107 } 1108 if (oldVersion < (8 << 16 | 6)) { 1109 // Add mvno_type, mvno_match_data fields to the APN. 1110 // The XML file does not change. 1111 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1112 " ADD COLUMN mvno_type TEXT DEFAULT '';"); 1113 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1114 " ADD COLUMN mvno_match_data TEXT DEFAULT '';"); 1115 oldVersion = 8 << 16 | 6; 1116 } 1117 if (oldVersion < (9 << 16 | 6)) { 1118 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1119 " ADD COLUMN sub_id INTEGER DEFAULT " + 1120 SubscriptionManager.INVALID_SUBSCRIPTION_ID + ";"); 1121 oldVersion = 9 << 16 | 6; 1122 } 1123 if (oldVersion < (10 << 16 | 6)) { 1124 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1125 " ADD COLUMN profile_id INTEGER DEFAULT 0;"); 1126 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1127 " ADD COLUMN modem_cognitive BOOLEAN DEFAULT 0;"); 1128 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1129 " ADD COLUMN max_conns INTEGER DEFAULT 0;"); 1130 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1131 " ADD COLUMN wait_time INTEGER DEFAULT 0;"); 1132 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1133 " ADD COLUMN max_conns_time INTEGER DEFAULT 0;"); 1134 oldVersion = 10 << 16 | 6; 1135 } 1136 if (oldVersion < (11 << 16 | 6)) { 1137 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + 1138 " ADD COLUMN mtu INTEGER DEFAULT 0;"); 1139 oldVersion = 11 << 16 | 6; 1140 } 1141 if (oldVersion < (12 << 16 | 6)) { 1142 try { 1143 // Try to update the siminfo table. It might not be there. 1144 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + 1145 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MCC + " INTEGER DEFAULT 0;"); 1146 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + 1147 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MNC + " INTEGER DEFAULT 0;"); 1148 } catch (SQLiteException e) { 1149 if (DBG) { 1150 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1151 " The table will get created in onOpen."); 1152 } 1153 } 1154 oldVersion = 12 << 16 | 6; 1155 } 1156 if (oldVersion < (13 << 16 | 6)) { 1157 try { 1158 // Try to update the siminfo table. It might not be there. 1159 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " + 1160 Telephony.SimInfo.COLUMN_CARRIER_NAME + " TEXT DEFAULT '';"); 1161 } catch (SQLiteException e) { 1162 if (DBG) { 1163 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1164 " The table will get created in onOpen."); 1165 } 1166 } 1167 oldVersion = 13 << 16 | 6; 1168 } 1169 if (oldVersion < (14 << 16 | 6)) { 1170 // Do nothing. This is to avoid recreating table twice. Table is anyway recreated 1171 // for next version and that takes care of updates for this version as well. 1172 // This version added a new column user_edited to carriers db. 1173 } 1174 if (oldVersion < (15 << 16 | 6)) { 1175 // Most devices should be upgrading from version 13. On upgrade new db will be 1176 // populated from the xml included in OTA but user and carrier edited/added entries 1177 // need to be preserved. This new version also adds new columns EDITED and 1178 // BEARER_BITMASK to the table. Upgrade steps from version 13 are: 1179 // 1. preserve user and carrier added/edited APNs (by comparing against 1180 // old-apns-conf.xml included in OTA) - done in preserveUserAndCarrierApns() 1181 // 2. add new columns EDITED and BEARER_BITMASK (create a new table for that) - done 1182 // in createCarriersTable() 1183 // 3. copy over preserved APNs from old table to new table - done in 1184 // copyPreservedApnsToNewTable() 1185 // The only exception if upgrading from version 14 is that EDITED field is already 1186 // present (but is called USER_EDITED) 1187 /********************************************************************************* 1188 * IMPORTANT NOTE: SINCE CARRIERS TABLE IS RECREATED HERE, IT WILL BE THE LATEST 1189 * VERSION AFTER THIS. AS A RESULT ANY SUBSEQUENT UPDATES TO THE TABLE WILL FAIL 1190 * (DUE TO COLUMN-ALREADY-EXISTS KIND OF EXCEPTION). ALL SUBSEQUENT UPDATES SHOULD 1191 * HANDLE THAT GRACEFULLY. 1192 *********************************************************************************/ 1193 Cursor c; 1194 String[] proj = {"_id"}; 1195 if (VDBG) { 1196 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null); 1197 log("dbh.onUpgrade:- before upgrading total number of rows: " + c.getCount()); 1198 } 1199 1200 // Compare db with old apns xml file so that any user or carrier edited/added 1201 // entries can be preserved across upgrade 1202 preserveUserAndCarrierApns(db); 1203 1204 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null); 1205 1206 if (VDBG) { 1207 log("dbh.onUpgrade:- after preserveUserAndCarrierApns() total number of " + 1208 "rows: " + ((c == null) ? 0 : c.getCount())); 1209 } 1210 1211 createCarriersTable(db, CARRIERS_TABLE_TMP); 1212 1213 copyPreservedApnsToNewTable(db, c); 1214 c.close(); 1215 1216 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE); 1217 1218 db.execSQL("ALTER TABLE " + CARRIERS_TABLE_TMP + " rename to " + CARRIERS_TABLE + 1219 ";"); 1220 1221 if (VDBG) { 1222 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null); 1223 log("dbh.onUpgrade:- after upgrading total number of rows: " + c.getCount()); 1224 c.close(); 1225 c = db.query(CARRIERS_TABLE, proj, IS_UNEDITED, null, null, null, null); 1226 log("dbh.onUpgrade:- after upgrading total number of rows with " + IS_UNEDITED + 1227 ": " + c.getCount()); 1228 c.close(); 1229 c = db.query(CARRIERS_TABLE, proj, IS_EDITED, null, null, null, null); 1230 log("dbh.onUpgrade:- after upgrading total number of rows with " + IS_EDITED + 1231 ": " + c.getCount()); 1232 c.close(); 1233 } 1234 1235 oldVersion = 15 << 16 | 6; 1236 } 1237 if (oldVersion < (16 << 16 | 6)) { 1238 try { 1239 // Try to update the siminfo table. It might not be there. 1240 // These columns may already be present in which case execSQL will throw an 1241 // exception 1242 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1243 + Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT 1244 + " INTEGER DEFAULT 1;"); 1245 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1246 + Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT 1247 + " INTEGER DEFAULT 1;"); 1248 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1249 + Telephony.SimInfo.COLUMN_CB_AMBER_ALERT + " INTEGER DEFAULT 1;"); 1250 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1251 + Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1;"); 1252 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1253 + Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION 1254 + " INTEGER DEFAULT 4;"); 1255 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1256 + Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL 1257 + " INTEGER DEFAULT 0;"); 1258 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1259 + Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE + " INTEGER DEFAULT 1;"); 1260 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1261 + Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH + " INTEGER DEFAULT 1;"); 1262 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1263 + Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0;"); 1264 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1265 + Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1;"); 1266 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1267 + Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0;"); 1268 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1269 + Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1;"); 1270 } catch (SQLiteException e) { 1271 if (DBG) { 1272 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1273 " The table will get created in onOpen."); 1274 } 1275 } 1276 oldVersion = 16 << 16 | 6; 1277 } 1278 if (oldVersion < (17 << 16 | 6)) { 1279 Cursor c = null; 1280 try { 1281 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null, 1282 String.valueOf(1)); 1283 if (c == null || c.getColumnIndex(USER_VISIBLE) == -1) { 1284 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " + 1285 USER_VISIBLE + " BOOLEAN DEFAULT 1;"); 1286 } else { 1287 if (DBG) { 1288 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. Column " + 1289 USER_VISIBLE + " already exists."); 1290 } 1291 } 1292 } finally { 1293 if (c != null) { 1294 c.close(); 1295 } 1296 } 1297 oldVersion = 17 << 16 | 6; 1298 } 1299 if (oldVersion < (18 << 16 | 6)) { 1300 try { 1301 // Try to update the siminfo table. It might not be there. 1302 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " + 1303 Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS + " INTEGER DEFAULT " + 1304 Telephony.SimInfo.SIM_PROVISIONED + ";"); 1305 } catch (SQLiteException e) { 1306 if (DBG) { 1307 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1308 " The table will get created in onOpen."); 1309 } 1310 } 1311 oldVersion = 18 << 16 | 6; 1312 } 1313 if (oldVersion < (19 << 16 | 6)) { 1314 // Do nothing. This is to avoid recreating table twice. Table is anyway recreated 1315 // for version 24 and that takes care of updates for this version as well. 1316 // This version added more fields protocol and roaming protocol to the primary key. 1317 } 1318 if (oldVersion < (20 << 16 | 6)) { 1319 try { 1320 // Try to update the siminfo table. It might not be there. 1321 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " + 1322 Telephony.SimInfo.COLUMN_IS_EMBEDDED + " INTEGER DEFAULT 0;"); 1323 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " + 1324 Telephony.SimInfo.COLUMN_ACCESS_RULES + " BLOB;"); 1325 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " + 1326 Telephony.SimInfo.COLUMN_IS_REMOVABLE + " INTEGER DEFAULT 0;"); 1327 } catch (SQLiteException e) { 1328 if (DBG) { 1329 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1330 "The table will get created in onOpen."); 1331 } 1332 } 1333 oldVersion = 20 << 16 | 6; 1334 } 1335 if (oldVersion < (21 << 16 | 6)) { 1336 try { 1337 // Try to update the carriers table. It might not be there. 1338 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " + 1339 USER_EDITABLE + " INTEGER DEFAULT 1;"); 1340 } catch (SQLiteException e) { 1341 // This is possible if the column already exists which may be the case if the 1342 // table was just created as part of upgrade to version 19 1343 if (DBG) { 1344 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " + 1345 "The table will get created in onOpen."); 1346 } 1347 } 1348 oldVersion = 21 << 16 | 6; 1349 } 1350 if (oldVersion < (22 << 16 | 6)) { 1351 try { 1352 // Try to update the siminfo table. It might not be there. 1353 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1354 + Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED 1355 + " INTEGER DEFAULT -1;"); 1356 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1357 + Telephony.SimInfo.COLUMN_VT_IMS_ENABLED + " INTEGER DEFAULT -1;"); 1358 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1359 + Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED + " INTEGER DEFAULT -1;"); 1360 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1361 + Telephony.SimInfo.COLUMN_WFC_IMS_MODE + " INTEGER DEFAULT -1;"); 1362 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1363 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1;"); 1364 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1365 + Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1;"); 1366 } catch (SQLiteException e) { 1367 if (DBG) { 1368 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " + 1369 "The table will get created in onOpen."); 1370 } 1371 } 1372 oldVersion = 22 << 16 | 6; 1373 } 1374 if (oldVersion < (23 << 16 | 6)) { 1375 try { 1376 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " + 1377 OWNED_BY + " INTEGER DEFAULT " + OWNED_BY_OTHERS + ";"); 1378 } catch (SQLiteException e) { 1379 if (DBG) { 1380 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " + 1381 "The table will get created in onOpen."); 1382 } 1383 } 1384 oldVersion = 23 << 16 | 6; 1385 } 1386 if (oldVersion < (24 << 16 | 6)) { 1387 Cursor c = null; 1388 String[] proj = {"_id"}; 1389 recreateDB(db, proj, /* version */24); 1390 if (VDBG) { 1391 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null); 1392 log("dbh.onUpgrade:- after upgrading total number of rows: " + c.getCount()); 1393 c.close(); 1394 c = db.query( 1395 CARRIERS_TABLE, proj, NETWORK_TYPE_BITMASK, null, null, null, null); 1396 log("dbh.onUpgrade:- after upgrading total number of rows with " 1397 + NETWORK_TYPE_BITMASK + ": " + c.getCount()); 1398 c.close(); 1399 } 1400 oldVersion = 24 << 16 | 6; 1401 } 1402 if (oldVersion < (25 << 16 | 6)) { 1403 // Add a new column SubscriptionManager.CARD_ID into the database and set the value 1404 // to be the same as the existing column SubscriptionManager.ICC_ID. In order to do 1405 // this, we need to first make a copy of the existing SIMINFO_TABLE, set the value 1406 // of the new column SubscriptionManager.CARD_ID, and replace the SIMINFO_TABLE with 1407 // the new table. 1408 Cursor c = null; 1409 String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID}; 1410 recreateSimInfoDB(c, db, proj); 1411 if (VDBG) { 1412 c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null); 1413 log("dbh.onUpgrade:- after upgrading " + SIMINFO_TABLE 1414 + " total number of rows: " + c.getCount()); 1415 c.close(); 1416 c = db.query(SIMINFO_TABLE, proj, Telephony.SimInfo.COLUMN_CARD_ID 1417 + " IS NOT NULL", null, null, null, null); 1418 log("dbh.onUpgrade:- after upgrading total number of rows with " 1419 + Telephony.SimInfo.COLUMN_CARD_ID + ": " + c.getCount()); 1420 c.close(); 1421 } 1422 oldVersion = 25 << 16 | 6; 1423 } 1424 if (oldVersion < (26 << 16 | 6)) { 1425 // Add a new column Carriers.APN_SET_ID into the database and set the value to 1426 // Carriers.NO_SET_SET by default. 1427 try { 1428 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " + 1429 APN_SET_ID + " INTEGER DEFAULT " + NO_APN_SET_ID + ";"); 1430 } catch (SQLiteException e) { 1431 if (DBG) { 1432 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " + 1433 "The table will get created in onOpen."); 1434 } 1435 } 1436 oldVersion = 26 << 16 | 6; 1437 } 1438 1439 if (oldVersion < (27 << 16 | 6)) { 1440 // Add the new MCC_STRING and MNC_STRING columns into the subscription table, 1441 // and attempt to populate them. 1442 try { 1443 // Try to update the siminfo table. It might not be there. 1444 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + 1445 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MCC_STRING + " TEXT;"); 1446 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + 1447 " ADD COLUMN " + Telephony.SimInfo.COLUMN_MNC_STRING + " TEXT;"); 1448 } catch (SQLiteException e) { 1449 if (DBG) { 1450 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1451 " The table will get created in onOpen."); 1452 } 1453 } 1454 // Migrate the old integer values over to strings 1455 String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, 1456 Telephony.SimInfo.COLUMN_MCC, Telephony.SimInfo.COLUMN_MNC}; 1457 try (Cursor c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null)) { 1458 while (c.moveToNext()) { 1459 fillInMccMncStringAtCursor(mContext, db, c); 1460 } 1461 } 1462 oldVersion = 27 << 16 | 6; 1463 } 1464 1465 if (oldVersion < (28 << 16 | 6)) { 1466 try { 1467 // Try to update the siminfo table. It might not be there. 1468 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1469 + Telephony.SimInfo.COLUMN_IS_OPPORTUNISTIC + " INTEGER DEFAULT 0;"); 1470 } catch (SQLiteException e) { 1471 if (DBG) { 1472 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1473 "The table will get created in onOpen."); 1474 } 1475 } 1476 oldVersion = 28 << 16 | 6; 1477 } 1478 1479 if (oldVersion < (29 << 16 | 6)) { 1480 try { 1481 // Add a new column Telephony.CARRIER_ID into the database and add UNIQUE 1482 // constraint into table. However, sqlite cannot add constraints to an existing 1483 // table, so recreate the table. 1484 String[] proj = {"_id"}; 1485 recreateDB(db, proj, /* version */29); 1486 } catch (SQLiteException e) { 1487 if (DBG) { 1488 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " + 1489 "The table will get created in onOpen."); 1490 } 1491 } 1492 oldVersion = 29 << 16 | 6; 1493 } 1494 1495 if (oldVersion < (30 << 16 | 6)) { 1496 try { 1497 // Try to update the siminfo table. It might not be there. 1498 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1499 + Telephony.SimInfo.COLUMN_GROUP_UUID + " TEXT;"); 1500 } catch (SQLiteException e) { 1501 if (DBG) { 1502 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1503 "The table will get created in onOpen."); 1504 } 1505 } 1506 oldVersion = 30 << 16 | 6; 1507 } 1508 1509 if (oldVersion < (31 << 16 | 6)) { 1510 try { 1511 // Try to update the siminfo table. It might not be there. 1512 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1513 + Telephony.SimInfo.COLUMN_IS_METERED + " INTEGER DEFAULT 1;"); 1514 } catch (SQLiteException e) { 1515 if (DBG) { 1516 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1517 "The table will get created in onOpen."); 1518 } 1519 } 1520 oldVersion = 31 << 16 | 6; 1521 } 1522 1523 if (oldVersion < (32 << 16 | 6)) { 1524 try { 1525 // Try to update the siminfo table. It might not be there. 1526 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1527 + Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE + " TEXT;"); 1528 } catch (SQLiteException e) { 1529 if (DBG) { 1530 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1531 "The table will get created in onOpen."); 1532 } 1533 } 1534 oldVersion = 32 << 16 | 6; 1535 } 1536 1537 if (oldVersion < (33 << 16 | 6)) { 1538 try { 1539 // Try to update the siminfo table. It might not be there. 1540 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1541 + Telephony.SimInfo.COLUMN_CARRIER_ID + " INTEGER DEFAULT -1;"); 1542 } catch (SQLiteException e) { 1543 if (DBG) { 1544 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1545 "The table will get created in onOpen."); 1546 } 1547 } 1548 oldVersion = 33 << 16 | 6; 1549 } 1550 1551 if (oldVersion < (34 << 16 | 6)) { 1552 try { 1553 // Try to update the siminfo table. It might not be there. 1554 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " + 1555 Telephony.SimInfo.COLUMN_PROFILE_CLASS + " INTEGER DEFAULT " + 1556 Telephony.SimInfo.PROFILE_CLASS_UNSET + ";"); 1557 } catch (SQLiteException e) { 1558 if (DBG) { 1559 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1560 "The table will get created in onOpen."); 1561 } 1562 } 1563 oldVersion = 34 << 16 | 6; 1564 } 1565 1566 if (oldVersion < (35 << 16 | 6)) { 1567 try { 1568 // Try to update the siminfo table. It might not be there. 1569 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1570 + Telephony.SimInfo.COLUMN_SUBSCRIPTION_TYPE + " INTEGER DEFAULT " 1571 + Telephony.SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM + ";"); 1572 } catch (SQLiteException e) { 1573 if (DBG) { 1574 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1575 "The table will get created in onOpen."); 1576 } 1577 } 1578 oldVersion = 35 << 16 | 6; 1579 } 1580 1581 if (oldVersion < (36 << 16 | 6)) { 1582 // Add a new column Carriers.SKIP_464XLAT into the database and set the value to 1583 // SKIP_464XLAT_DEFAULT. 1584 try { 1585 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " + 1586 SKIP_464XLAT + " INTEGER DEFAULT " + SKIP_464XLAT_DEFAULT + ";"); 1587 } catch (SQLiteException e) { 1588 if (DBG) { 1589 log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " + 1590 "The table will get created in onOpen."); 1591 } 1592 } 1593 oldVersion = 36 << 16 | 6; 1594 } 1595 1596 if (oldVersion < (37 << 16 | 6)) { 1597 // Add new columns Telephony.SimInfo.EHPLMNS and Telephony.SimInfo.HPLMNS into 1598 // the database. 1599 try { 1600 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + 1601 " ADD COLUMN " + Telephony.SimInfo.COLUMN_EHPLMNS + " TEXT;"); 1602 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + 1603 " ADD COLUMN " + Telephony.SimInfo.COLUMN_HPLMNS + " TEXT;"); 1604 } catch (SQLiteException e) { 1605 if (DBG) { 1606 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade for ehplmns. " + 1607 "The table will get created in onOpen."); 1608 } 1609 } 1610 oldVersion = 37 << 16 | 6; 1611 } 1612 1613 if (oldVersion < (39 << 16 | 6)) { 1614 try { 1615 // Try to update the siminfo table. It might not be there. 1616 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1617 + Telephony.SimInfo.COLUMN_GROUP_OWNER + " TEXT;"); 1618 } catch (SQLiteException e) { 1619 if (DBG) { 1620 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1621 "The table will get created in onOpen."); 1622 } 1623 } 1624 oldVersion = 39 << 16 | 6; 1625 } 1626 1627 if (oldVersion < (40 << 16 | 6)) { 1628 try { 1629 // Try to update the siminfo table. It might not be there. 1630 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1631 + Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES + " TEXT;"); 1632 } catch (SQLiteException e) { 1633 if (DBG) { 1634 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1635 "The table will get created in onOpen."); 1636 } 1637 } 1638 oldVersion = 40 << 16 | 6; 1639 } 1640 1641 if (oldVersion < (41 << 16 | 6)) { 1642 try { 1643 // Try to update the siminfo table. It might not be there. 1644 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1645 + Telephony.SimInfo.COLUMN_IMSI + " TEXT;"); 1646 } catch (SQLiteException e) { 1647 if (DBG) { 1648 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1649 "The table will get created in onOpen."); 1650 } 1651 } 1652 oldVersion = 41 << 16 | 6; 1653 } 1654 1655 if (oldVersion < (42 << 16 | 6)) { 1656 try { 1657 // Try to update the siminfo table. It might not be there. 1658 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " + 1659 Telephony.SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS + " BLOB;"); 1660 } catch (SQLiteException e) { 1661 if (DBG) { 1662 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1663 "The table will get created in onOpen."); 1664 } 1665 } 1666 } 1667 1668 if (oldVersion < (43 << 16 | 6)) { 1669 try { 1670 // Try to update the siminfo table. It might not be there. 1671 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1672 + Telephony.SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED 1673 + " INTEGER DEFAULT 1;"); 1674 } catch (SQLiteException e) { 1675 if (DBG) { 1676 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1677 "The table will get created in onOpen."); 1678 } 1679 } 1680 oldVersion = 43 << 16 | 6; 1681 } 1682 1683 if (oldVersion < (44 << 16 | 6)) { 1684 try { 1685 // Try to update the siminfo table. It might not be there. 1686 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1687 + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES 1688 + " BIGINT DEFAULT -1;"); 1689 } catch (SQLiteException e) { 1690 if (DBG) { 1691 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1692 "The table will get created in onOpen."); 1693 } 1694 } 1695 oldVersion = 44 << 16 | 6; 1696 } 1697 1698 if (oldVersion < (45 << 16 | 6)) { 1699 try { 1700 // Try to update the siminfo table. It might not be there. 1701 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1702 + Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED 1703 + " INTEGER DEFAULT 0;"); 1704 } catch (SQLiteException e) { 1705 if (DBG) { 1706 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1707 "The table will get created in onOpen."); 1708 } 1709 } 1710 oldVersion = 45 << 16 | 6; 1711 } 1712 1713 if (oldVersion < (46 << 16 | 6)) { 1714 try { 1715 // Try to update the siminfo table. It might not be there. 1716 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1717 + Telephony.SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED 1718 + " INTEGER DEFAULT 0;"); 1719 } catch (SQLiteException e) { 1720 if (DBG) { 1721 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1722 "The table will get created in onOpen."); 1723 } 1724 } 1725 oldVersion = 46 << 16 | 6; 1726 } 1727 1728 if (oldVersion < (47 << 16 | 6)) { 1729 try { 1730 // Try to update the siminfo table. It might not be there. 1731 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1732 + Telephony.SimInfo.COLUMN_RCS_CONFIG 1733 + " BLOB;"); 1734 } catch (SQLiteException e) { 1735 if (DBG) { 1736 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1737 "The table will get created in onOpen."); 1738 } 1739 } 1740 oldVersion = 47 << 16 | 6; 1741 } 1742 1743 if (oldVersion < (48 << 16 | 6)) { 1744 try { 1745 // Try to update the siminfo table. It might not be there. 1746 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1747 + Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS 1748 + " TEXT;"); 1749 } catch (SQLiteException e) { 1750 if (DBG) { 1751 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1752 "The table will get created in onOpen."); 1753 } 1754 } 1755 try { 1756 // Migrate the old Long values over to String 1757 String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, 1758 Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES}; 1759 try (Cursor c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null)) { 1760 while (c.moveToNext()) { 1761 fillInAllowedNetworkTypesStringAtCursor(db, c); 1762 } 1763 } 1764 1765 } catch (SQLiteException e) { 1766 if (DBG) { 1767 log("can't migrate value from COLUMN_ALLOWED_NETWORK_TYPES to " 1768 + "COLUMN_ALLOWED_NETWORK_TYPES_ALL_REASON"); 1769 } 1770 } 1771 oldVersion = 48 << 16 | 6; 1772 } 1773 1774 if (oldVersion < (49 << 16 | 6)) { 1775 try { 1776 // Try to update the siminfo table. It might not be there. 1777 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1778 + Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING 1779 + " INTEGER DEFAULT 0;"); 1780 } catch (SQLiteException e) { 1781 if (DBG) { 1782 log("onUpgrade failed to updated " + SIMINFO_TABLE 1783 + " to add d2d status sharing column. "); 1784 } 1785 } 1786 } 1787 1788 if (oldVersion < (50 << 16 | 6)) { 1789 try { 1790 // Try to update the siminfo table. It might not be there. 1791 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1792 + Telephony.SimInfo.COLUMN_VOIMS_OPT_IN_STATUS 1793 + " INTEGER DEFAULT 0;"); 1794 } catch (SQLiteException e) { 1795 if (DBG) { 1796 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1797 "The table will get created in onOpen."); 1798 } 1799 } 1800 oldVersion = 50 << 16 | 6; 1801 } 1802 1803 if (oldVersion < (51 << 16 | 6)) { 1804 try { 1805 // Try to update the siminfo table. It might not be there. 1806 db.execSQL("ALERT TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1807 + Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS 1808 + " TEXT;"); 1809 } catch (SQLiteException e) { 1810 if (DBG) { 1811 log("onUpgrade failed to updated " + SIMINFO_TABLE 1812 + " to add d2d status sharing contacts. "); 1813 } 1814 } 1815 oldVersion = 51 << 16 | 6; 1816 } 1817 1818 if (oldVersion < (52 << 16 | 6)) { 1819 try { 1820 // Try to update the siminfo table. It might not be there. 1821 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1822 + Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED 1823 + " INTEGER DEFAULT -1;"); 1824 } catch (SQLiteException e) { 1825 if (DBG) { 1826 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1827 "The table will get created in onOpen."); 1828 } 1829 } 1830 oldVersion = 52 << 16 | 6; 1831 } 1832 1833 if (oldVersion < (53 << 16 | 6)) { 1834 try { 1835 // Try to update the siminfo table. Fix typo error in version 51. 1836 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1837 + Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS 1838 + " TEXT;"); 1839 } catch (SQLiteException e) { 1840 if (DBG) { 1841 log("onUpgrade failed to updated " + SIMINFO_TABLE 1842 + " to add d2d status sharing contacts. "); 1843 } 1844 } 1845 oldVersion = 53 << 16 | 6; 1846 } 1847 1848 if (oldVersion < (54 << 16 | 6)) { 1849 try { 1850 // Try to update the siminfo table with new columns. 1851 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1852 + Telephony.SimInfo.COLUMN_PHONE_NUMBER_SOURCE_CARRIER 1853 + " TEXT;"); 1854 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1855 + Telephony.SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS 1856 + " TEXT;"); 1857 } catch (SQLiteException e) { 1858 if (DBG) { 1859 log("onUpgrade failed to update " + SIMINFO_TABLE 1860 + " to add phone numbers. "); 1861 } 1862 } 1863 oldVersion = 54 << 16 | 6; 1864 } 1865 1866 if (oldVersion < (55 << 16 | 6)) { 1867 try { 1868 // Try to add new fields LINGERING_NETWORK_TYPE_BITMASK, ALWAYS_ON, 1869 // MTU_V4, and MTU_V6 1870 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " 1871 + LINGERING_NETWORK_TYPE_BITMASK + " INTEGER DEFAULT 0;"); 1872 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " 1873 + ALWAYS_ON + " INTEGER DEFAULT 0;"); 1874 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " 1875 + MTU_V4 + " INTEGER DEFAULT 0;"); 1876 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " 1877 + MTU_V6 + " INTEGER DEFAULT 0;"); 1878 // Populate MTU_V4 with MTU values 1879 db.execSQL("UPDATE " + CARRIERS_TABLE + " SET " + MTU_V4 + " = " 1880 + MTU + " WHERE " + MTU + " != 0;"); 1881 } catch (SQLiteException e) { 1882 if (DBG) { 1883 log("onUpgrade failed to update " + CARRIERS_TABLE 1884 + " to add lingering network type bitmask, always on flag," 1885 + " and MTU v4 and v6 values."); 1886 } 1887 } 1888 oldVersion = 55 << 16 | 6; 1889 } 1890 1891 if (oldVersion < (56 << 16 | 6)) { 1892 try { 1893 // Try to update the siminfo table. It might not be there. 1894 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1895 + Telephony.SimInfo.COLUMN_PORT_INDEX 1896 + " INTEGER DEFAULT -1;"); 1897 } catch (SQLiteException e) { 1898 if (DBG) { 1899 log("onUpgrade skipping " + SIMINFO_TABLE + " upgrade. " + 1900 "The table will get created in onOpen."); 1901 } 1902 } 1903 oldVersion = 56 << 16 | 6; 1904 } 1905 1906 if (oldVersion < (57 << 16 | 6)) { 1907 try { 1908 // Try to update the siminfo table. It might not be there. 1909 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1910 + Telephony.SimInfo.COLUMN_USAGE_SETTING 1911 + " INTEGER DEFAULT " + SubscriptionManager.USAGE_SETTING_UNKNOWN 1912 + ";"); 1913 } catch (SQLiteException e) { 1914 if (DBG) { 1915 log("onUpgrade failed to updated " + SIMINFO_TABLE 1916 + " to add preferred usage setting"); 1917 } 1918 } 1919 oldVersion = 57 << 16 | 6; 1920 } 1921 1922 if (oldVersion < (58 << 16 | 6)) { 1923 try { 1924 // Try to update the siminfo table with new columns. 1925 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1926 + Telephony.SimInfo.COLUMN_TP_MESSAGE_REF 1927 + " INTEGER DEFAULT -1;"); 1928 } catch (SQLiteException e) { 1929 if (DBG) { 1930 log("onUpgrade failed to update " + SIMINFO_TABLE 1931 + " to add message Reference. "); 1932 } 1933 } 1934 oldVersion = 58 << 16 | 6; 1935 } 1936 1937 if (oldVersion < (59 << 16 | 6)) { 1938 try { 1939 // Try to update the siminfo table with new columns. 1940 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1941 + Telephony.SimInfo.COLUMN_USER_HANDLE 1942 + " INTEGER DEFAULT " + UserHandle.USER_NULL +";"); 1943 } catch (SQLiteException e) { 1944 if (DBG) { 1945 log("onUpgrade failed to update " + SIMINFO_TABLE 1946 + " to add message Reference. "); 1947 } 1948 } 1949 oldVersion = 59 << 16 | 6; 1950 } 1951 if (oldVersion < (60 << 16 | 6)) { 1952 // Update the siminfo table with new column enabled_data_mobile_policies 1953 // and set its value to be a copy of data_enabled_override_rules. 1954 try { 1955 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 1956 + Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES 1957 + " TEXT;"); 1958 } catch (SQLiteException e) { 1959 if (DBG) { 1960 log("onUpgrade failed to insert " 1961 +Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES +" to " 1962 + SIMINFO_TABLE); 1963 } 1964 } 1965 // Migrate the old Long values over to String 1966 String[] proj = {Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, 1967 Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES}; 1968 try (Cursor c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null)) { 1969 while (c.moveToNext()) { 1970 fillInEnabledMobileDataPoliciesAtCursor(db, c); 1971 } 1972 } catch (SQLiteException e) { 1973 if (DBG) { 1974 log("can't migrate value from COLUMN_DATA_ENABLED_OVERRIDE_RULES to " 1975 + "COLUMN_ENABLED_MOBILE_DATA_POLICIES"); 1976 } 1977 } 1978 oldVersion = 60 << 16 | 6; 1979 } 1980 1981 if (oldVersion < (61 << 16 | 6)) { 1982 try { 1983 // If default value of USER_HANDLE column is set to -1, then update it to -10000 1984 db.execSQL("UPDATE " + SIMINFO_TABLE + " SET " 1985 + Telephony.SimInfo.COLUMN_USER_HANDLE + "=" + UserHandle.USER_NULL 1986 + " WHERE " + Telephony.SimInfo.COLUMN_USER_HANDLE + "=-1;"); 1987 } catch (SQLiteException e) { 1988 if (DBG) { 1989 log("onUpgrade failed to update " + SIMINFO_TABLE 1990 + " to add message Reference. "); 1991 } 1992 } 1993 oldVersion = 61 << 16 | 6; 1994 } 1995 1996 if (oldVersion < (62 << 16 | 6)) { 1997 try { 1998 // Try to update the siminfo table with new columns. 1999 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2000 + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED 2001 + " INTEGER DEFAULT 0;"); 2002 } catch (SQLiteException e) { 2003 if (DBG) { 2004 log("onUpgrade failed to update " + SIMINFO_TABLE 2005 + " to add satellite enabled. "); 2006 } 2007 } 2008 oldVersion = 62 << 16 | 6; 2009 } 2010 2011 if (oldVersion < (63 << 16 | 6)) { 2012 try { 2013 // Try to update the siminfo table with new columns. 2014 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2015 + Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER 2016 + " INTEGER DEFAULT 0;"); 2017 } catch (SQLiteException e) { 2018 if (DBG) { 2019 log("onUpgrade failed to update " + SIMINFO_TABLE 2020 + " to add satellite attach for carrier enabled by user. "); 2021 } 2022 } 2023 oldVersion = 63 << 16 | 6; 2024 } 2025 2026 if (oldVersion < (64 << 16 | 6)) { 2027 try { 2028 /* If default value of COLUMN_SATELLITE_ENABLED column is set to -1, then update 2029 it to 0 */ 2030 db.execSQL("UPDATE " + SIMINFO_TABLE + " SET " 2031 + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + "=0" 2032 + " WHERE " + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + "=-1;"); 2033 /* If default value of COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER column is set 2034 to -1, then update it to 0 */ 2035 db.execSQL("UPDATE " + SIMINFO_TABLE + " SET " 2036 + Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER + "=0" 2037 + " WHERE " 2038 + Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER 2039 + "=-1;"); 2040 2041 // Try to update the siminfo table with new columns. 2042 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2043 + Telephony.SimInfo.COLUMN_IS_ONLY_NTN 2044 + " INTEGER DEFAULT 0;"); 2045 } catch (SQLiteException e) { 2046 if (DBG) { 2047 log("onUpgrade failed to update " + SIMINFO_TABLE 2048 + " to add satellite is ntn. "); 2049 } 2050 } 2051 oldVersion = 64 << 16 | 6; 2052 } 2053 2054 if (oldVersion < (65 << 16 | 6)) { 2055 try { 2056 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " 2057 + INFRASTRUCTURE_BITMASK + " INTEGER DEFAULT 1;"); 2058 } catch (SQLiteException e) { 2059 if (DBG) { 2060 log("onUpgrade failed to update " + CARRIERS_TABLE 2061 + " to add infrastructure bitmask value."); 2062 } 2063 } 2064 oldVersion = 65 << 16 | 6; 2065 } 2066 2067 if (oldVersion < (66 << 16 | 6)) { 2068 try { 2069 // Try to add new field ESIM_BOOTSTRAP_PROVISIONING 2070 db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " 2071 + ESIM_BOOTSTRAP_PROVISIONING + " INTEGER DEFAULT 0;"); 2072 } catch (SQLiteException e) { 2073 if (DBG) { 2074 log("onUpgrade failed to update " + CARRIERS_TABLE 2075 + " to add esim bootstrap provisioning flag"); 2076 } 2077 2078 } 2079 oldVersion = 66 << 16 | 6; 2080 } 2081 2082 if (oldVersion < (67 << 16 | 6)) { 2083 try { 2084 // If default value of infrastructure_bitmask column is set to 1, then update 2085 // it to 3 2086 db.execSQL("UPDATE " + CARRIERS_TABLE + " SET " + INFRASTRUCTURE_BITMASK + "=3" 2087 + " WHERE " + INFRASTRUCTURE_BITMASK + "=1;"); 2088 } catch (SQLiteException e) { 2089 if (DBG) { 2090 log("onUpgrade failed to update " + CARRIERS_TABLE 2091 + " to add infrastructure bitmask value."); 2092 } 2093 } 2094 oldVersion = 67 << 16 | 6; 2095 } 2096 2097 if (oldVersion < (68 << 16 | 6)) { 2098 try { 2099 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2100 + Telephony.SimInfo.COLUMN_SERVICE_CAPABILITIES 2101 + " INTEGER DEFAULT 7;"); 2102 } catch (SQLiteException e) { 2103 if (DBG) { 2104 log("onUpgrade failed to update " + SIMINFO_TABLE 2105 + " to add cellular service capabilities"); 2106 } 2107 2108 } 2109 oldVersion = 68 << 16 | 6; 2110 } 2111 2112 if (oldVersion < (69 << 16 | 6)) { 2113 try { 2114 // If default value of COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER column is 2115 // set to 0, then update it to 1 2116 db.execSQL("UPDATE " + SIMINFO_TABLE + " SET " 2117 + Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER + "=1" 2118 + " WHERE " 2119 + Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER 2120 + "=0;"); 2121 } catch (SQLiteException e) { 2122 if (DBG) { 2123 log("onUpgrade failed to update " + SIMINFO_TABLE 2124 + " to add cellular service capabilities"); 2125 } 2126 } 2127 oldVersion = 69 << 16 | 6; 2128 } 2129 if (oldVersion < (70 << 16 | 6)) { 2130 try { 2131 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2132 + Telephony.SimInfo.COLUMN_TRANSFER_STATUS 2133 + " INTEGER DEFAULT 0;"); 2134 } catch (SQLiteException e) { 2135 if (DBG) { 2136 log("onUpgrade failed to update " + SIMINFO_TABLE 2137 + " to add transfer status"); 2138 } 2139 2140 } 2141 oldVersion = 70 << 16 | 6; 2142 } 2143 2144 if (oldVersion < (71 << 16 | 6)) { 2145 try { 2146 // Try to update the siminfo table with new columns. 2147 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2148 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS 2149 + " INTEGER DEFAULT 0;"); 2150 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2151 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS 2152 + " TEXT DEFAULT '';"); 2153 } catch (SQLiteException e) { 2154 if (DBG) { 2155 log("onUpgrade failed to update " + SIMINFO_TABLE 2156 + " to add satellite entitlement status and plmns"); 2157 } 2158 } 2159 oldVersion = 71 << 16 | 6; 2160 } 2161 2162 if (oldVersion < (72 << 16 | 6)) { 2163 try { 2164 // Try to update the siminfo table with new columns. 2165 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2166 + Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED 2167 + " INTEGER DEFAULT 0;"); 2168 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2169 + Telephony.SimInfo.COLUMN_IS_ONLY_NTN + " INTEGER DEFAULT 0;"); 2170 2171 // Copy the value of the previous column (COLUMN_IS_NTN) to the new column 2172 // (COLUMN_IS_ONLY_NTN) for all rows in the sim_info table. 2173 final String columnIsNtn = "is_ntn"; 2174 db.execSQL("UPDATE " + SIMINFO_TABLE + " SET " 2175 + Telephony.SimInfo.COLUMN_IS_ONLY_NTN + " = " + columnIsNtn + ";"); 2176 2177 // ALTER TABLE siminfo DROP is_ntn; 2178 db.execSQL( 2179 "ALTER TABLE " + SIMINFO_TABLE + " DROP COLUMN " + columnIsNtn + ";"); 2180 } catch (SQLiteException e) { 2181 if (DBG) { 2182 log("onUpgrade failed to update " + SIMINFO_TABLE 2183 + " to add is satellite esos supported"); 2184 } 2185 } 2186 oldVersion = 72 << 16 | 6; 2187 } 2188 2189 if (oldVersion < (73 << 16 | 6)) { 2190 try { 2191 // Try to update the siminfo table with new columns. 2192 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2193 + Telephony.SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM 2194 + " INTEGER DEFAULT 0;"); 2195 } catch (SQLiteException e) { 2196 if (DBG) { 2197 log("onUpgrade failed to update " + SIMINFO_TABLE 2198 + " to add satellite is provisioned"); 2199 } 2200 } 2201 oldVersion = 73 << 16 | 6; 2202 } 2203 2204 if (oldVersion < (74 << 16 | 6)) { 2205 try { 2206 // Try to update the siminfo table with new columns. 2207 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2208 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS 2209 + " TEXT DEFAULT '';"); 2210 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2211 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS 2212 + " TEXT DEFAULT '';"); 2213 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2214 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP 2215 + " TEXT DEFAULT '';"); 2216 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2217 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY 2218 + " TEXT DEFAULT '';"); 2219 db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN " 2220 + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY 2221 + " TEXT DEFAULT '';"); 2222 } catch (SQLiteException e) { 2223 if (DBG) { 2224 log("onUpgrade failed to update " + SIMINFO_TABLE 2225 + " to add satellite entitlement data"); 2226 } 2227 } 2228 oldVersion = 74 << 16 | 6; 2229 } 2230 if (DBG) { 2231 log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion); 2232 } 2233 // when adding fields to onUpgrade, also add a unit test to TelephonyDatabaseHelperTest 2234 // and update the DATABASE_VERSION field and add a column in copyAllApnValues 2235 } 2236 recreateSimInfoDB(Cursor c, SQLiteDatabase db, String[] proj)2237 private void recreateSimInfoDB(Cursor c, SQLiteDatabase db, String[] proj) { 2238 if (VDBG) { 2239 c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null); 2240 log("dbh.onUpgrade:+ before upgrading " + SIMINFO_TABLE + 2241 " total number of rows: " + c.getCount()); 2242 c.close(); 2243 } 2244 2245 // Sort in ascending order by subscription id to make sure the rows do not get flipped 2246 // during the query and added in the new sim info table in another order (sub id is 2247 // stored in settings between migrations). 2248 c = db.query(SIMINFO_TABLE, null, null, null, null, null, ORDER_BY_SUB_ID); 2249 2250 db.execSQL("DROP TABLE IF EXISTS " + SIMINFO_TABLE_TMP); 2251 2252 createSimInfoTable(db, SIMINFO_TABLE_TMP); 2253 2254 copySimInfoDataToTmpTable(db, c); 2255 c.close(); 2256 2257 db.execSQL("DROP TABLE IF EXISTS " + SIMINFO_TABLE); 2258 2259 db.execSQL("ALTER TABLE " + SIMINFO_TABLE_TMP + " rename to " + SIMINFO_TABLE + ";"); 2260 2261 } 2262 copySimInfoDataToTmpTable(SQLiteDatabase db, Cursor c)2263 private void copySimInfoDataToTmpTable(SQLiteDatabase db, Cursor c) { 2264 // Move entries from SIMINFO_TABLE to SIMINFO_TABLE_TMP 2265 if (c != null) { 2266 while (c.moveToNext()) { 2267 ContentValues cv = new ContentValues(); 2268 copySimInfoValuesV24(cv, c); 2269 // The card ID is supposed to be the ICCID of the profile for UICC card, and 2270 // the EID of the card for eUICC card. Since EID is unknown for old entries in 2271 // SIMINFO_TABLE, we use ICCID as the card ID for all the old entries while 2272 // upgrading the SIMINFO_TABLE. In UiccController, both the card ID and ICCID 2273 // will be checked when user queries the slot information using the card ID 2274 // from the database. 2275 getCardIdfromIccid(cv, c); 2276 try { 2277 db.insert(SIMINFO_TABLE_TMP, null, cv); 2278 if (VDBG) { 2279 log("dbh.copySimInfoDataToTmpTable: db.insert returned >= 0; " + 2280 "insert successful for cv " + cv); 2281 } 2282 } catch (SQLException e) { 2283 if (VDBG) 2284 log("dbh.copySimInfoDataToTmpTable insertWithOnConflict exception " + 2285 e + " for cv " + cv); 2286 } 2287 } 2288 } 2289 } 2290 copySimInfoValuesV24(ContentValues cv, Cursor c)2291 private void copySimInfoValuesV24(ContentValues cv, Cursor c) { 2292 // String vals 2293 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ICC_ID); 2294 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DISPLAY_NAME); 2295 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CARRIER_NAME); 2296 getStringValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_NUMBER); 2297 2298 // bool/int vals 2299 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_SIM_SLOT_INDEX); 2300 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_NAME_SOURCE); 2301 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_COLOR); 2302 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DISPLAY_NUMBER_FORMAT); 2303 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_DATA_ROAMING); 2304 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_MCC); 2305 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_MNC); 2306 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_SIM_PROVISIONING_STATUS); 2307 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_IS_EMBEDDED); 2308 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_IS_REMOVABLE); 2309 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT); 2310 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT); 2311 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_AMBER_ALERT); 2312 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_EMERGENCY_ALERT); 2313 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_SOUND_DURATION); 2314 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL); 2315 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_VIBRATE); 2316 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ALERT_SPEECH); 2317 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_ETWS_TEST_ALERT); 2318 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_CHANNEL_50_ALERT); 2319 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_CMAS_TEST_ALERT); 2320 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_CB_OPT_OUT_DIALOG); 2321 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED); 2322 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_VT_IMS_ENABLED); 2323 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED); 2324 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_MODE); 2325 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE); 2326 getIntValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED); 2327 2328 // Blob vals 2329 getBlobValueFromCursor(cv, c, Telephony.SimInfo.COLUMN_ACCESS_RULES); 2330 } 2331 getCardIdfromIccid(ContentValues cv, Cursor c)2332 private void getCardIdfromIccid(ContentValues cv, Cursor c) { 2333 int columnIndex = c.getColumnIndex(Telephony.SimInfo.COLUMN_ICC_ID); 2334 if (columnIndex != -1) { 2335 String fromCursor = c.getString(columnIndex); 2336 if (!TextUtils.isEmpty(fromCursor)) { 2337 cv.put(Telephony.SimInfo.COLUMN_CARD_ID, fromCursor); 2338 } 2339 } 2340 } 2341 recreateDB(SQLiteDatabase db, String[] proj, int version)2342 private void recreateDB(SQLiteDatabase db, String[] proj, int version) { 2343 // Upgrade steps are: 2344 // 1. Create a temp table- done in createCarriersTable() 2345 // 2. copy over APNs from old table to new table - done in copyDataToTmpTable() 2346 // 3. Drop the existing table. 2347 // 4. Copy over the tmp table. 2348 Cursor c; 2349 if (VDBG) { 2350 c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null); 2351 log("dbh.onUpgrade:- before upgrading total number of rows: " + c.getCount()); 2352 c.close(); 2353 } 2354 2355 c = db.query(CARRIERS_TABLE, null, null, null, null, null, null); 2356 2357 if (VDBG) { 2358 log("dbh.onUpgrade:- starting data copy of existing rows: " + 2359 + ((c == null) ? 0 : c.getCount())); 2360 } 2361 2362 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE_TMP); 2363 2364 createCarriersTable(db, CARRIERS_TABLE_TMP); 2365 2366 copyDataToTmpTable(db, c, version); 2367 c.close(); 2368 2369 db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE); 2370 2371 db.execSQL("ALTER TABLE " + CARRIERS_TABLE_TMP + " rename to " + CARRIERS_TABLE + ";"); 2372 } 2373 preserveUserAndCarrierApns(SQLiteDatabase db)2374 private void preserveUserAndCarrierApns(SQLiteDatabase db) { 2375 if (VDBG) log("preserveUserAndCarrierApns"); 2376 XmlPullParser confparser; 2377 File confFile = new File(Environment.getRootDirectory(), OLD_APNS_PATH); 2378 FileReader confreader = null; 2379 try { 2380 confreader = new FileReader(confFile); 2381 confparser = Xml.newPullParser(); 2382 confparser.setInput(confreader); 2383 XmlUtils.beginDocument(confparser, "apns"); 2384 2385 deleteMatchingApns(db, confparser); 2386 } catch (FileNotFoundException e) { 2387 // This function is called only when upgrading db to version 15. Details about the 2388 // upgrade are mentioned in onUpgrade(). This file missing means user/carrier added 2389 // APNs cannot be preserved. Log an error message so that OEMs know they need to 2390 // include old apns file for comparison. 2391 loge("PRESERVEUSERANDCARRIERAPNS: " + OLD_APNS_PATH + 2392 " NOT FOUND. IT IS NEEDED TO UPGRADE FROM OLDER VERSIONS OF APN " + 2393 "DB WHILE PRESERVING USER/CARRIER ADDED/EDITED ENTRIES."); 2394 } catch (Exception e) { 2395 loge("preserveUserAndCarrierApns: Exception while parsing '" + 2396 confFile.getAbsolutePath() + "'" + e); 2397 } finally { 2398 if (confreader != null) { 2399 try { 2400 confreader.close(); 2401 } catch (IOException e) { 2402 // do nothing 2403 } 2404 } 2405 } 2406 } 2407 deleteMatchingApns(SQLiteDatabase db, XmlPullParser parser)2408 private void deleteMatchingApns(SQLiteDatabase db, XmlPullParser parser) { 2409 if (VDBG) log("deleteMatchingApns"); 2410 if (parser != null) { 2411 if (VDBG) log("deleteMatchingApns: parser != null"); 2412 try { 2413 XmlUtils.nextElement(parser); 2414 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { 2415 ContentValues row = getRow(parser, false); 2416 if (row == null) { 2417 throw new XmlPullParserException("Expected 'apn' tag", parser, null); 2418 } 2419 deleteRow(db, row); 2420 XmlUtils.nextElement(parser); 2421 } 2422 } catch (XmlPullParserException e) { 2423 loge("deleteMatchingApns: Got XmlPullParserException while deleting apns." + e); 2424 } catch (IOException e) { 2425 loge("deleteMatchingApns: Got IOException while deleting apns." + e); 2426 } catch (SQLException e) { 2427 loge("deleteMatchingApns: Got SQLException while deleting apns." + e); 2428 } 2429 } 2430 } 2431 queryValFirst(String field)2432 private String queryValFirst(String field) { 2433 return field + "=?"; 2434 } 2435 queryVal(String field)2436 private String queryVal(String field) { 2437 return " and " + field + "=?"; 2438 } 2439 queryValOrNull(String field)2440 private String queryValOrNull(String field) { 2441 return " and (" + field + "=? or " + field + " is null)"; 2442 } 2443 queryVal2OrNull(String field)2444 private String queryVal2OrNull(String field) { 2445 return " and (" + field + "=? or " + field + "=? or " + field + " is null)"; 2446 } 2447 deleteRow(SQLiteDatabase db, ContentValues values)2448 private void deleteRow(SQLiteDatabase db, ContentValues values) { 2449 if (VDBG) log("deleteRow"); 2450 String where = queryValFirst(NUMERIC) + 2451 queryVal(MNC) + 2452 queryVal(MNC) + 2453 queryValOrNull(APN) + 2454 queryValOrNull(USER) + 2455 queryValOrNull(SERVER) + 2456 queryValOrNull(PASSWORD) + 2457 queryValOrNull(PROXY) + 2458 queryValOrNull(PORT) + 2459 queryValOrNull(MMSPROXY) + 2460 queryValOrNull(MMSPORT) + 2461 queryValOrNull(MMSC) + 2462 queryValOrNull(AUTH_TYPE) + 2463 queryValOrNull(TYPE) + 2464 queryValOrNull(PROTOCOL) + 2465 queryValOrNull(ROAMING_PROTOCOL) + 2466 queryVal2OrNull(CARRIER_ENABLED) + 2467 queryValOrNull(BEARER) + 2468 queryValOrNull(MVNO_TYPE) + 2469 queryValOrNull(MVNO_MATCH_DATA) + 2470 queryValOrNull(PROFILE_ID) + 2471 queryVal2OrNull(MODEM_PERSIST) + 2472 queryValOrNull(MAX_CONNECTIONS) + 2473 queryValOrNull(WAIT_TIME_RETRY) + 2474 queryValOrNull(TIME_LIMIT_FOR_MAX_CONNECTIONS) + 2475 queryValOrNull(MTU) + 2476 queryValOrNull(MTU_V4) + 2477 queryValOrNull(MTU_V6); 2478 String[] whereArgs = new String[31]; 2479 int i = 0; 2480 whereArgs[i++] = values.getAsString(NUMERIC); 2481 whereArgs[i++] = values.getAsString(MCC); 2482 whereArgs[i++] = values.getAsString(MNC); 2483 whereArgs[i++] = values.getAsString(NAME); 2484 whereArgs[i++] = values.containsKey(APN) ? 2485 values.getAsString(APN) : ""; 2486 whereArgs[i++] = values.containsKey(USER) ? 2487 values.getAsString(USER) : ""; 2488 whereArgs[i++] = values.containsKey(SERVER) ? 2489 values.getAsString(SERVER) : ""; 2490 whereArgs[i++] = values.containsKey(PASSWORD) ? 2491 values.getAsString(PASSWORD) : ""; 2492 whereArgs[i++] = values.containsKey(PROXY) ? 2493 values.getAsString(PROXY) : ""; 2494 whereArgs[i++] = values.containsKey(PORT) ? 2495 values.getAsString(PORT) : ""; 2496 whereArgs[i++] = values.containsKey(MMSPROXY) ? 2497 values.getAsString(MMSPROXY) : ""; 2498 whereArgs[i++] = values.containsKey(MMSPORT) ? 2499 values.getAsString(MMSPORT) : ""; 2500 whereArgs[i++] = values.containsKey(MMSC) ? 2501 values.getAsString(MMSC) : ""; 2502 whereArgs[i++] = values.containsKey(AUTH_TYPE) ? 2503 values.getAsString(AUTH_TYPE) : "-1"; 2504 whereArgs[i++] = values.containsKey(TYPE) ? 2505 values.getAsString(TYPE) : ""; 2506 whereArgs[i++] = values.containsKey(PROTOCOL) ? 2507 values.getAsString(PROTOCOL) : DEFAULT_PROTOCOL; 2508 whereArgs[i++] = values.containsKey(ROAMING_PROTOCOL) ? 2509 values.getAsString(ROAMING_PROTOCOL) : DEFAULT_ROAMING_PROTOCOL; 2510 2511 if (values.containsKey(CARRIER_ENABLED)) { 2512 whereArgs[i++] = convertStringToBoolString(values.getAsString(CARRIER_ENABLED)); 2513 whereArgs[i++] = convertStringToIntString(values.getAsString(CARRIER_ENABLED)); 2514 } else { 2515 String defaultIntString = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(CARRIER_ENABLED); 2516 whereArgs[i++] = convertStringToBoolString(defaultIntString); 2517 whereArgs[i++] = defaultIntString; 2518 } 2519 2520 whereArgs[i++] = values.containsKey(BEARER) ? 2521 values.getAsString(BEARER) : "0"; 2522 whereArgs[i++] = values.containsKey(MVNO_TYPE) ? 2523 values.getAsString(MVNO_TYPE) : ""; 2524 whereArgs[i++] = values.containsKey(MVNO_MATCH_DATA) ? 2525 values.getAsString(MVNO_MATCH_DATA) : ""; 2526 whereArgs[i++] = values.containsKey(PROFILE_ID) ? 2527 values.getAsString(PROFILE_ID) : "0"; 2528 2529 if (values.containsKey(MODEM_PERSIST) && 2530 (values.getAsString(MODEM_PERSIST). 2531 equalsIgnoreCase("true") || 2532 values.getAsString(MODEM_PERSIST).equals("1"))) { 2533 whereArgs[i++] = "true"; 2534 whereArgs[i++] = "1"; 2535 } else { 2536 whereArgs[i++] = "false"; 2537 whereArgs[i++] = "0"; 2538 } 2539 2540 whereArgs[i++] = values.containsKey(MAX_CONNECTIONS) ? 2541 values.getAsString(MAX_CONNECTIONS) : "0"; 2542 whereArgs[i++] = values.containsKey(WAIT_TIME_RETRY) ? 2543 values.getAsString(WAIT_TIME_RETRY) : "0"; 2544 whereArgs[i++] = values.containsKey(TIME_LIMIT_FOR_MAX_CONNECTIONS) ? 2545 values.getAsString(TIME_LIMIT_FOR_MAX_CONNECTIONS) : "0"; 2546 whereArgs[i++] = values.containsKey(MTU) ? 2547 values.getAsString(MTU) : "0"; 2548 whereArgs[i++] = values.containsKey(MTU_V4) ? 2549 values.getAsString(MTU_V4) : "0"; 2550 whereArgs[i++] = values.containsKey(MTU_V6) ? 2551 values.getAsString(MTU_V6) : "0"; 2552 2553 if (VDBG) { 2554 log("deleteRow: where: " + where); 2555 2556 StringBuilder builder = new StringBuilder(); 2557 for (String s : whereArgs) { 2558 builder.append(s + ", "); 2559 } 2560 2561 log("deleteRow: whereArgs: " + builder.toString()); 2562 } 2563 db.delete(CARRIERS_TABLE, where, whereArgs); 2564 } 2565 copyDataToTmpTable(SQLiteDatabase db, Cursor c, int version)2566 private void copyDataToTmpTable(SQLiteDatabase db, Cursor c, int version) { 2567 // Move entries from CARRIERS_TABLE to CARRIERS_TABLE_TMP 2568 if (c != null) { 2569 while (c.moveToNext()) { 2570 ContentValues cv = new ContentValues(); 2571 copyAllApnValues(cv, c); 2572 if (version == 24) { 2573 // Sync bearer bitmask and network type bitmask 2574 getNetworkTypeBitmaskFromCursor(cv, c); 2575 } 2576 try { 2577 db.insertWithOnConflict(CARRIERS_TABLE_TMP, null, cv, 2578 SQLiteDatabase.CONFLICT_ABORT); 2579 if (VDBG) { 2580 log("dbh.copyPreservedApnsToNewTable: db.insert returned >= 0; " + 2581 "insert successful for cv " + cv); 2582 } 2583 } catch (SQLException e) { 2584 if (VDBG) 2585 log("dbh.copyPreservedApnsToNewTable insertWithOnConflict exception " + 2586 e + " for cv " + cv); 2587 } 2588 } 2589 } 2590 } 2591 copyApnValuesV17(ContentValues cv, Cursor c)2592 private void copyApnValuesV17(ContentValues cv, Cursor c) { 2593 // Include only non-null values in cv so that null values can be replaced 2594 // with default if there's a default value for the field 2595 2596 // String vals 2597 getStringValueFromCursor(cv, c, NAME); 2598 getStringValueFromCursor(cv, c, NUMERIC); 2599 getStringValueFromCursor(cv, c, MCC); 2600 getStringValueFromCursor(cv, c, MNC); 2601 getStringValueFromCursor(cv, c, APN); 2602 getStringValueFromCursor(cv, c, USER); 2603 getStringValueFromCursor(cv, c, SERVER); 2604 getStringValueFromCursor(cv, c, PASSWORD); 2605 getStringValueFromCursor(cv, c, PROXY); 2606 getStringValueFromCursor(cv, c, PORT); 2607 getStringValueFromCursor(cv, c, MMSPROXY); 2608 getStringValueFromCursor(cv, c, MMSPORT); 2609 getStringValueFromCursor(cv, c, MMSC); 2610 getStringValueFromCursor(cv, c, TYPE); 2611 getStringValueFromCursor(cv, c, PROTOCOL); 2612 getStringValueFromCursor(cv, c, ROAMING_PROTOCOL); 2613 getStringValueFromCursor(cv, c, MVNO_TYPE); 2614 getStringValueFromCursor(cv, c, MVNO_MATCH_DATA); 2615 2616 // bool/int vals 2617 getIntValueFromCursor(cv, c, AUTH_TYPE); 2618 getIntValueFromCursor(cv, c, CURRENT); 2619 getIntValueFromCursor(cv, c, CARRIER_ENABLED); 2620 getIntValueFromCursor(cv, c, BEARER); 2621 getIntValueFromCursor(cv, c, SUBSCRIPTION_ID); 2622 getIntValueFromCursor(cv, c, PROFILE_ID); 2623 getIntValueFromCursor(cv, c, MODEM_PERSIST); 2624 getIntValueFromCursor(cv, c, MAX_CONNECTIONS); 2625 getIntValueFromCursor(cv, c, WAIT_TIME_RETRY); 2626 getIntValueFromCursor(cv, c, TIME_LIMIT_FOR_MAX_CONNECTIONS); 2627 getIntValueFromCursor(cv, c, MTU); 2628 getIntValueFromCursor(cv, c, BEARER_BITMASK); 2629 getIntValueFromCursor(cv, c, EDITED_STATUS); 2630 getIntValueFromCursor(cv, c, USER_VISIBLE); 2631 } 2632 copyAllApnValues(ContentValues cv, Cursor c)2633 private void copyAllApnValues(ContentValues cv, Cursor c) { 2634 // String vals 2635 getStringValueFromCursor(cv, c, NAME); 2636 getStringValueFromCursor(cv, c, NUMERIC); 2637 getStringValueFromCursor(cv, c, MCC); 2638 getStringValueFromCursor(cv, c, MNC); 2639 getStringValueFromCursor(cv, c, APN); 2640 getStringValueFromCursor(cv, c, USER); 2641 getStringValueFromCursor(cv, c, SERVER); 2642 getStringValueFromCursor(cv, c, PASSWORD); 2643 getStringValueFromCursor(cv, c, PROXY); 2644 getStringValueFromCursor(cv, c, PORT); 2645 getStringValueFromCursor(cv, c, MMSPROXY); 2646 getStringValueFromCursor(cv, c, MMSPORT); 2647 getStringValueFromCursor(cv, c, MMSC); 2648 getStringValueFromCursor(cv, c, TYPE); 2649 getStringValueFromCursor(cv, c, PROTOCOL); 2650 getStringValueFromCursor(cv, c, ROAMING_PROTOCOL); 2651 getStringValueFromCursor(cv, c, MVNO_TYPE); 2652 getStringValueFromCursor(cv, c, MVNO_MATCH_DATA); 2653 2654 // bool/int vals 2655 getIntValueFromCursor(cv, c, AUTH_TYPE); 2656 getIntValueFromCursor(cv, c, CURRENT); 2657 getIntValueFromCursor(cv, c, CARRIER_ENABLED); 2658 getIntValueFromCursor(cv, c, BEARER); 2659 getIntValueFromCursor(cv, c, SUBSCRIPTION_ID); 2660 getIntValueFromCursor(cv, c, PROFILE_ID); 2661 getIntValueFromCursor(cv, c, MODEM_PERSIST); 2662 getIntValueFromCursor(cv, c, MAX_CONNECTIONS); 2663 getIntValueFromCursor(cv, c, WAIT_TIME_RETRY); 2664 getIntValueFromCursor(cv, c, TIME_LIMIT_FOR_MAX_CONNECTIONS); 2665 getIntValueFromCursor(cv, c, MTU); 2666 getIntValueFromCursor(cv, c, MTU_V4); 2667 getIntValueFromCursor(cv, c, MTU_V6); 2668 getIntValueFromCursor(cv, c, NETWORK_TYPE_BITMASK); 2669 getIntValueFromCursor(cv, c, LINGERING_NETWORK_TYPE_BITMASK); 2670 getIntValueFromCursor(cv, c, BEARER_BITMASK); 2671 getIntValueFromCursor(cv, c, EDITED_STATUS); 2672 getIntValueFromCursor(cv, c, USER_VISIBLE); 2673 getIntValueFromCursor(cv, c, USER_EDITABLE); 2674 getIntValueFromCursor(cv, c, OWNED_BY); 2675 getIntValueFromCursor(cv, c, APN_SET_ID); 2676 getIntValueFromCursor(cv, c, SKIP_464XLAT); 2677 getIntValueFromCursor(cv, c, ALWAYS_ON); 2678 getIntValueFromCursor(cv, c, INFRASTRUCTURE_BITMASK); 2679 getIntValueFromCursor(cv, c, ESIM_BOOTSTRAP_PROVISIONING); 2680 } 2681 copyPreservedApnsToNewTable(SQLiteDatabase db, Cursor c)2682 private void copyPreservedApnsToNewTable(SQLiteDatabase db, Cursor c) { 2683 // Move entries from CARRIERS_TABLE to CARRIERS_TABLE_TMP 2684 if (c != null && mContext.getResources() != null) { 2685 try { 2686 String[] persistApnsForPlmns = mContext.getResources().getStringArray( 2687 R.array.persist_apns_for_plmn); 2688 while (c.moveToNext()) { 2689 ContentValues cv = new ContentValues(); 2690 String val; 2691 // Using V17 copy function for V15 upgrade. This should be fine since it 2692 // handles columns that may not exist properly (getStringValueFromCursor() 2693 // and getIntValueFromCursor() handle column index -1) 2694 copyApnValuesV17(cv, c); 2695 // Change bearer to a bitmask 2696 String bearerStr = c.getString(c.getColumnIndex(BEARER)); 2697 if (!TextUtils.isEmpty(bearerStr)) { 2698 int bearer_bitmask = getBitmaskForTech(Integer.parseInt(bearerStr)); 2699 cv.put(BEARER_BITMASK, bearer_bitmask); 2700 2701 int networkTypeBitmask = rilRadioTechnologyToNetworkTypeBitmask( 2702 Integer.parseInt(bearerStr)); 2703 cv.put(NETWORK_TYPE_BITMASK, networkTypeBitmask); 2704 } 2705 2706 int userEditedColumnIdx = c.getColumnIndex("user_edited"); 2707 if (userEditedColumnIdx != -1) { 2708 String user_edited = c.getString(userEditedColumnIdx); 2709 if (!TextUtils.isEmpty(user_edited)) { 2710 cv.put(EDITED_STATUS, new Integer(user_edited)); 2711 } 2712 } else { 2713 cv.put(EDITED_STATUS, CARRIER_EDITED); 2714 } 2715 2716 // New EDITED column. Default value (UNEDITED) will 2717 // be used for all rows except for non-mvno entries for plmns indicated 2718 // by resource: those will be set to CARRIER_EDITED to preserve 2719 // their current values 2720 val = c.getString(c.getColumnIndex(NUMERIC)); 2721 for (String s : persistApnsForPlmns) { 2722 if (!TextUtils.isEmpty(val) && val.equals(s) && 2723 (!cv.containsKey(MVNO_TYPE) || 2724 TextUtils.isEmpty(cv.getAsString(MVNO_TYPE)))) { 2725 if (userEditedColumnIdx == -1) { 2726 cv.put(EDITED_STATUS, CARRIER_EDITED); 2727 } else { // if (oldVersion == 14) -- if db had user_edited column 2728 if (cv.getAsInteger(EDITED_STATUS) == USER_EDITED) { 2729 cv.put(EDITED_STATUS, CARRIER_EDITED); 2730 } 2731 } 2732 2733 break; 2734 } 2735 } 2736 2737 try { 2738 db.insertWithOnConflict(CARRIERS_TABLE_TMP, null, cv, 2739 SQLiteDatabase.CONFLICT_ABORT); 2740 if (VDBG) { 2741 log("dbh.copyPreservedApnsToNewTable: db.insert returned >= 0; " + 2742 "insert successful for cv " + cv); 2743 } 2744 } catch (SQLException e) { 2745 if (VDBG) 2746 log("dbh.copyPreservedApnsToNewTable insertWithOnConflict exception " + 2747 e + " for cv " + cv); 2748 // Insertion failed which could be due to a conflict. Check if that is 2749 // the case and merge the entries 2750 Cursor oldRow = selectConflictingRow(db, 2751 CARRIERS_TABLE_TMP, cv); 2752 if (oldRow != null) { 2753 ContentValues mergedValues = new ContentValues(); 2754 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE_TMP, oldRow, cv, 2755 mergedValues, true, mContext); 2756 oldRow.close(); 2757 } 2758 } 2759 } 2760 } catch (Resources.NotFoundException e) { 2761 loge("array.persist_apns_for_plmn is not found"); 2762 return; 2763 } 2764 } 2765 } 2766 getStringValueFromCursor(ContentValues cv, Cursor c, String key)2767 private void getStringValueFromCursor(ContentValues cv, Cursor c, String key) { 2768 int columnIndex = c.getColumnIndex(key); 2769 if (columnIndex != -1) { 2770 String fromCursor = c.getString(columnIndex); 2771 if (fromCursor != null) { 2772 cv.put(key, fromCursor); 2773 } 2774 } 2775 } 2776 2777 /** 2778 * If NETWORK_TYPE_BITMASK does not exist (upgrade from version 23 to version 24), generate 2779 * NETWORK_TYPE_BITMASK with the use of BEARER_BITMASK. If NETWORK_TYPE_BITMASK existed 2780 * (upgrade from version 24 to forward), always map NETWORK_TYPE_BITMASK to BEARER_BITMASK. 2781 */ getNetworkTypeBitmaskFromCursor(ContentValues cv, Cursor c)2782 private void getNetworkTypeBitmaskFromCursor(ContentValues cv, Cursor c) { 2783 int columnIndex = c.getColumnIndex(NETWORK_TYPE_BITMASK); 2784 if (columnIndex != -1) { 2785 getStringValueFromCursor(cv, c, NETWORK_TYPE_BITMASK); 2786 // Map NETWORK_TYPE_BITMASK to BEARER_BITMASK if NETWORK_TYPE_BITMASK existed; 2787 String fromCursor = c.getString(columnIndex); 2788 if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) { 2789 int networkBitmask = Integer.valueOf(fromCursor); 2790 int bearerBitmask = convertNetworkTypeBitmaskToBearerBitmask(networkBitmask); 2791 cv.put(BEARER_BITMASK, String.valueOf(bearerBitmask)); 2792 } 2793 return; 2794 } 2795 columnIndex = c.getColumnIndex(BEARER_BITMASK); 2796 if (columnIndex != -1) { 2797 String fromCursor = c.getString(columnIndex); 2798 if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) { 2799 int bearerBitmask = Integer.valueOf(fromCursor); 2800 int networkBitmask = convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask); 2801 cv.put(NETWORK_TYPE_BITMASK, String.valueOf(networkBitmask)); 2802 } 2803 } 2804 } 2805 getIntValueFromCursor(ContentValues cv, Cursor c, String key)2806 private void getIntValueFromCursor(ContentValues cv, Cursor c, String key) { 2807 int columnIndex = c.getColumnIndex(key); 2808 if (columnIndex != -1) { 2809 String fromCursor = c.getString(columnIndex); 2810 if (!TextUtils.isEmpty(fromCursor)) { 2811 try { 2812 cv.put(key, new Integer(fromCursor)); 2813 } catch (NumberFormatException nfe) { 2814 // do nothing 2815 } 2816 } 2817 } 2818 } 2819 getBlobValueFromCursor(ContentValues cv, Cursor c, String key)2820 private void getBlobValueFromCursor(ContentValues cv, Cursor c, String key) { 2821 int columnIndex = c.getColumnIndex(key); 2822 if (columnIndex != -1) { 2823 byte[] fromCursor = c.getBlob(columnIndex); 2824 if (fromCursor != null) { 2825 cv.put(key, fromCursor); 2826 } 2827 } 2828 } 2829 2830 /** 2831 * Gets the next row of apn values. 2832 * 2833 * @param parser the parser 2834 * @param isOverlay If the xml file comes from an overlay MCC/MNC are treated as integers 2835 * @return the row or null if it's not an apn 2836 */ getRow(XmlPullParser parser, boolean isOverlay)2837 private ContentValues getRow(XmlPullParser parser, boolean isOverlay) { 2838 if (!"apn".equals(parser.getName())) { 2839 return null; 2840 } 2841 2842 ContentValues map = new ContentValues(); 2843 2844 String mcc = parser.getAttributeValue(null, "mcc"); 2845 String mnc = parser.getAttributeValue(null, "mnc"); 2846 String mccString = mcc; 2847 String mncString = mnc; 2848 // Since an mnc can have both two and three digits and it is hard to verify 2849 // all OEM's Global APN lists we only do this for overlays. 2850 if (isOverlay && mcc !=null && mnc != null) { 2851 mccString = String.format("%03d", Integer.parseInt(mcc)); 2852 // Looks up a two digit mnc in the carrier id DB 2853 // if not found a three digit mnc value is chosen 2854 mncString = getBestStringMnc(mContext, mccString, Integer.parseInt(mnc)); 2855 } 2856 // Make sure to set default values for numeric, mcc and mnc. This is the empty string. 2857 // If default is not set here, a duplicate of each carrier id APN will be created next 2858 // time the apn list is read. This happens at OTA or at restore. 2859 String numeric = (mccString == null | mncString == null) ? "" : mccString + mncString; 2860 map.put(NUMERIC, numeric); 2861 map.put(MCC, mccString != null ? mccString : ""); 2862 map.put(MNC, mncString != null ? mncString : ""); 2863 map.put(NAME, parser.getAttributeValue(null, "carrier")); 2864 2865 // do not add NULL to the map so that default values can be inserted in db 2866 addStringAttribute(parser, "apn", map, APN); 2867 addStringAttribute(parser, "user", map, USER); 2868 addStringAttribute(parser, "server", map, SERVER); 2869 addStringAttribute(parser, "password", map, PASSWORD); 2870 addStringAttribute(parser, "proxy", map, PROXY); 2871 addStringAttribute(parser, "port", map, PORT); 2872 addStringAttribute(parser, "mmsproxy", map, MMSPROXY); 2873 addStringAttribute(parser, "mmsport", map, MMSPORT); 2874 addStringAttribute(parser, "mmsc", map, MMSC); 2875 2876 String apnType = parser.getAttributeValue(null, "type"); 2877 if (apnType != null) { 2878 // Remove spaces before putting it in the map. 2879 apnType = apnType.replaceAll("\\s+", ""); 2880 map.put(TYPE, apnType); 2881 } 2882 2883 addStringAttribute(parser, "protocol", map, PROTOCOL); 2884 addStringAttribute(parser, "roaming_protocol", map, ROAMING_PROTOCOL); 2885 2886 addIntAttribute(parser, "authtype", map, AUTH_TYPE); 2887 addIntAttribute(parser, "bearer", map, BEARER); 2888 addIntAttribute(parser, "profile_id", map, PROFILE_ID); 2889 addIntAttribute(parser, "max_conns", map, MAX_CONNECTIONS); 2890 addIntAttribute(parser, "wait_time", map, WAIT_TIME_RETRY); 2891 addIntAttribute(parser, "max_conns_time", map, TIME_LIMIT_FOR_MAX_CONNECTIONS); 2892 addIntAttribute(parser, "mtu", map, MTU); 2893 addIntAttribute(parser, "mtu_v4", map, MTU_V4); 2894 addIntAttribute(parser, "mtu_v6", map, MTU_V6); 2895 addIntAttribute(parser, "apn_set_id", map, APN_SET_ID); 2896 addIntAttribute(parser, "carrier_id", map, CARRIER_ID); 2897 addIntAttribute(parser, "skip_464xlat", map, SKIP_464XLAT); 2898 2899 addBoolAttribute(parser, "carrier_enabled", map, CARRIER_ENABLED); 2900 addBoolAttribute(parser, "modem_cognitive", map, MODEM_PERSIST); 2901 addBoolAttribute(parser, "user_visible", map, USER_VISIBLE); 2902 addBoolAttribute(parser, "user_editable", map, USER_EDITABLE); 2903 addBoolAttribute(parser, "always_on", map, ALWAYS_ON); 2904 addBoolAttribute(parser, "esim_bootstrap_provisioning", map, 2905 ESIM_BOOTSTRAP_PROVISIONING); 2906 2907 int infrastructureBitmask = 2908 ApnSetting.INFRASTRUCTURE_CELLULAR | ApnSetting.INFRASTRUCTURE_SATELLITE; 2909 String infrastructureList = parser.getAttributeValue(null, "infrastructure_bitmask"); 2910 if (infrastructureList != null) { 2911 infrastructureBitmask = getInfrastructureListFromString(infrastructureList); 2912 } 2913 map.put(INFRASTRUCTURE_BITMASK, infrastructureBitmask); 2914 2915 int networkTypeBitmask = 0; 2916 String networkTypeList = parser.getAttributeValue(null, "network_type_bitmask"); 2917 if (networkTypeList != null) { 2918 networkTypeBitmask = getBitmaskFromString(networkTypeList); 2919 } 2920 map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask); 2921 2922 int lingeringNetworkTypeBitmask = 0; 2923 String lingeringNetworkTypeList = 2924 parser.getAttributeValue(null, "lingering_network_type_bitmask"); 2925 if (lingeringNetworkTypeList != null) { 2926 lingeringNetworkTypeBitmask = getBitmaskFromString(lingeringNetworkTypeList); 2927 } 2928 map.put(LINGERING_NETWORK_TYPE_BITMASK, lingeringNetworkTypeBitmask); 2929 2930 int bearerBitmask = 0; 2931 if (networkTypeList != null) { 2932 bearerBitmask = convertNetworkTypeBitmaskToBearerBitmask(networkTypeBitmask); 2933 } else { 2934 String bearerList = parser.getAttributeValue(null, "bearer_bitmask"); 2935 if (bearerList != null) { 2936 bearerBitmask = getBitmaskFromString(bearerList); 2937 } 2938 // Update the network type bitmask to keep them sync. 2939 networkTypeBitmask = convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask); 2940 map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask); 2941 } 2942 map.put(BEARER_BITMASK, bearerBitmask); 2943 2944 String mvno_type = parser.getAttributeValue(null, "mvno_type"); 2945 if (mvno_type != null) { 2946 String mvno_match_data = parser.getAttributeValue(null, "mvno_match_data"); 2947 if (mvno_match_data != null) { 2948 map.put(MVNO_TYPE, mvno_type); 2949 map.put(MVNO_MATCH_DATA, mvno_match_data); 2950 } 2951 } 2952 return map; 2953 } 2954 addStringAttribute(XmlPullParser parser, String att, ContentValues map, String key)2955 private void addStringAttribute(XmlPullParser parser, String att, 2956 ContentValues map, String key) { 2957 String val = parser.getAttributeValue(null, att); 2958 if (val != null) { 2959 map.put(key, val); 2960 } 2961 } 2962 addIntAttribute(XmlPullParser parser, String att, ContentValues map, String key)2963 private void addIntAttribute(XmlPullParser parser, String att, 2964 ContentValues map, String key) { 2965 String val = parser.getAttributeValue(null, att); 2966 if (val != null) { 2967 map.put(key, Integer.parseInt(val)); 2968 } 2969 } 2970 addBoolAttribute(XmlPullParser parser, String att, ContentValues map, String key)2971 private void addBoolAttribute(XmlPullParser parser, String att, 2972 ContentValues map, String key) { 2973 String val = parser.getAttributeValue(null, att); 2974 if (val != null) { 2975 map.put(key, Boolean.parseBoolean(val)); 2976 } 2977 } 2978 2979 /* 2980 * Loads apns from xml file into the database 2981 * 2982 * @param db the sqlite database to write to 2983 * @param parser the xml parser 2984 * @param isOverlay, if we are parsing an xml in an overlay 2985 */ loadApns(SQLiteDatabase db, XmlPullParser parser, boolean isOverlay)2986 private void loadApns(SQLiteDatabase db, XmlPullParser parser, boolean isOverlay) { 2987 if (parser != null) { 2988 try { 2989 db.beginTransaction(); 2990 XmlUtils.nextElement(parser); 2991 while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { 2992 ContentValues row = getRow(parser, isOverlay); 2993 if (row == null) { 2994 throw new XmlPullParserException("Expected 'apn' tag", parser, null); 2995 } 2996 insertAddingDefaults(db, row); 2997 XmlUtils.nextElement(parser); 2998 } 2999 db.setTransactionSuccessful(); 3000 } catch (XmlPullParserException e) { 3001 loge("Got XmlPullParserException while loading apns." + e); 3002 } catch (IOException e) { 3003 loge("Got IOException while loading apns." + e); 3004 } catch (SQLException e) { 3005 loge("Got SQLException while loading apns." + e); 3006 } finally { 3007 db.endTransaction(); 3008 } 3009 } 3010 } 3011 insertAddingDefaults(SQLiteDatabase db, ContentValues row)3012 private void insertAddingDefaults(SQLiteDatabase db, ContentValues row) { 3013 row = setDefaultValue(row); 3014 try { 3015 db.insertWithOnConflict(CARRIERS_TABLE, null, row, SQLiteDatabase.CONFLICT_ABORT); 3016 if (VDBG) log("dbh.insertAddingDefaults: db.insert returned >= 0; insert " + 3017 "successful for cv " + row); 3018 } catch (SQLException e) { 3019 if (VDBG) log("dbh.insertAddingDefaults: exception " + e); 3020 // Insertion failed which could be due to a conflict. Check if that is the case and 3021 // update edited field accordingly. 3022 // Search for the exact same entry and update edited field. 3023 // If it is USER_EDITED/CARRIER_EDITED change it to UNEDITED, 3024 // and if USER/CARRIER_DELETED change it to USER/CARRIER_DELETED_BUT_PRESENT_IN_XML. 3025 Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, row); 3026 if (oldRow != null) { 3027 // Update the row 3028 ContentValues mergedValues = new ContentValues(); 3029 int edited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS)); 3030 int old_edited = edited; 3031 if (edited != UNEDITED) { 3032 if (edited == USER_DELETED) { 3033 // USER_DELETED_BUT_PRESENT_IN_XML indicates entry has been deleted 3034 // by user but present in apn xml file. 3035 edited = USER_DELETED_BUT_PRESENT_IN_XML; 3036 } else if (edited == CARRIER_DELETED) { 3037 // CARRIER_DELETED_BUT_PRESENT_IN_XML indicates entry has been deleted 3038 // by user but present in apn xml file. 3039 edited = CARRIER_DELETED_BUT_PRESENT_IN_XML; 3040 } 3041 mergedValues.put(EDITED_STATUS, edited); 3042 } 3043 3044 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, row, mergedValues, false, 3045 mContext); 3046 3047 if (VDBG) log("dbh.insertAddingDefaults: old edited = " + old_edited 3048 + " new edited = " + edited); 3049 3050 oldRow.close(); 3051 } 3052 } 3053 } 3054 } 3055 mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow, ContentValues newRow, ContentValues mergedValues, boolean onUpgrade, Context context)3056 public static void mergeFieldsAndUpdateDb(SQLiteDatabase db, String table, Cursor oldRow, 3057 ContentValues newRow, ContentValues mergedValues, 3058 boolean onUpgrade, Context context) { 3059 if (newRow.containsKey(TYPE)) { 3060 // Merge the types 3061 String oldType = oldRow.getString(oldRow.getColumnIndex(TYPE)); 3062 String newType = newRow.getAsString(TYPE); 3063 3064 if (!oldType.equalsIgnoreCase(newType)) { 3065 if (oldType.equals("") || newType.equals("")) { 3066 newRow.put(TYPE, ""); 3067 } else { 3068 String[] oldTypes = oldType.toLowerCase(Locale.ROOT).split(","); 3069 String[] newTypes = newType.toLowerCase(Locale.ROOT).split(","); 3070 3071 if (VDBG) { 3072 log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" + 3073 oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex( 3074 BEARER_BITMASK)) + " old networkType=" + 3075 oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)) + 3076 " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex( 3077 PROFILE_ID)) + " newRow " + newRow); 3078 } 3079 3080 // If separate rows are needed, do not need to merge any further 3081 if (separateRowsNeeded(db, table, oldRow, newRow, context, oldTypes, 3082 newTypes)) { 3083 if (VDBG) log("mergeFieldsAndUpdateDb: separateRowsNeeded() returned " + 3084 "true"); 3085 return; 3086 } 3087 3088 // Merge the 2 types 3089 ArrayList<String> mergedTypes = new ArrayList<String>(); 3090 mergedTypes.addAll(Arrays.asList(oldTypes)); 3091 for (String s : newTypes) { 3092 if (!mergedTypes.contains(s.trim())) { 3093 mergedTypes.add(s); 3094 } 3095 } 3096 StringBuilder mergedType = new StringBuilder(); 3097 for (int i = 0; i < mergedTypes.size(); i++) { 3098 mergedType.append((i == 0 ? "" : ",") + mergedTypes.get(i)); 3099 } 3100 newRow.put(TYPE, mergedType.toString()); 3101 } 3102 } 3103 mergedValues.put(TYPE, newRow.getAsString(TYPE)); 3104 } 3105 3106 if (newRow.containsKey(BEARER_BITMASK)) { 3107 int oldBearer = oldRow.getInt(oldRow.getColumnIndex(BEARER_BITMASK)); 3108 int newBearer = newRow.getAsInteger(BEARER_BITMASK); 3109 if (oldBearer != newBearer) { 3110 if (oldBearer == 0 || newBearer == 0) { 3111 newRow.put(BEARER_BITMASK, 0); 3112 } else { 3113 newRow.put(BEARER_BITMASK, (oldBearer | newBearer)); 3114 } 3115 } 3116 mergedValues.put(BEARER_BITMASK, newRow.getAsInteger(BEARER_BITMASK)); 3117 } 3118 3119 if (newRow.containsKey(NETWORK_TYPE_BITMASK)) { 3120 int oldBitmask = oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)); 3121 int newBitmask = newRow.getAsInteger(NETWORK_TYPE_BITMASK); 3122 if (oldBitmask != newBitmask) { 3123 if (oldBitmask == 0 || newBitmask == 0) { 3124 newRow.put(NETWORK_TYPE_BITMASK, 0); 3125 } else { 3126 newRow.put(NETWORK_TYPE_BITMASK, (oldBitmask | newBitmask)); 3127 } 3128 } 3129 mergedValues.put(NETWORK_TYPE_BITMASK, newRow.getAsInteger(NETWORK_TYPE_BITMASK)); 3130 } 3131 3132 if (newRow.containsKey(BEARER_BITMASK) 3133 && newRow.containsKey(NETWORK_TYPE_BITMASK)) { 3134 syncBearerBitmaskAndNetworkTypeBitmask(mergedValues); 3135 } 3136 3137 if (!onUpgrade) { 3138 // Do not overwrite a carrier or user edit with EDITED=UNEDITED 3139 if (newRow.containsKey(EDITED_STATUS)) { 3140 int oldEdited = oldRow.getInt(oldRow.getColumnIndex(EDITED_STATUS)); 3141 int newEdited = newRow.getAsInteger(EDITED_STATUS); 3142 if (newEdited == UNEDITED && (oldEdited == CARRIER_EDITED 3143 || oldEdited == CARRIER_DELETED 3144 || oldEdited == CARRIER_DELETED_BUT_PRESENT_IN_XML 3145 || oldEdited == USER_EDITED 3146 || oldEdited == USER_DELETED 3147 || oldEdited == USER_DELETED_BUT_PRESENT_IN_XML)) { 3148 newRow.remove(EDITED_STATUS); 3149 } 3150 } 3151 mergedValues.putAll(newRow); 3152 } 3153 3154 if (mergedValues.size() > 0) { 3155 db.update(table, mergedValues, "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), 3156 null); 3157 } 3158 } 3159 separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow, ContentValues newRow, Context context, String[] oldTypes, String[] newTypes)3160 private static boolean separateRowsNeeded(SQLiteDatabase db, String table, Cursor oldRow, 3161 ContentValues newRow, Context context, 3162 String[] oldTypes, String[] newTypes) { 3163 // If this APN falls under persist_apns_for_plmn, and the 3164 // only difference between old type and new type is that one has dun, and 3165 // the APNs have profile_id 0 or not set, then set the profile_id to 1 for 3166 // the dun APN/remove dun from type. This will ensure both oldRow and newRow exist 3167 // separately in db. 3168 3169 boolean match = false; 3170 3171 // Check if APN falls under persist_apns_for_plmn 3172 if (context.getResources() != null) { 3173 String[] persistApnsForPlmns = context.getResources().getStringArray( 3174 R.array.persist_apns_for_plmn); 3175 for (String s : persistApnsForPlmns) { 3176 if (s.equalsIgnoreCase(newRow.getAsString(NUMERIC))) { 3177 match = true; 3178 break; 3179 } 3180 } 3181 } else { 3182 loge("separateRowsNeeded: resources=null"); 3183 } 3184 3185 if (!match) return false; 3186 3187 // APN falls under persist_apns_for_plmn 3188 // Check if only difference between old type and new type is that 3189 // one has dun 3190 ArrayList<String> oldTypesAl = new ArrayList<String>(Arrays.asList(oldTypes)); 3191 ArrayList<String> newTypesAl = new ArrayList<String>(Arrays.asList(newTypes)); 3192 ArrayList<String> listWithDun = null; 3193 ArrayList<String> listWithoutDun = null; 3194 boolean dunInOld = false; 3195 if (oldTypesAl.size() == newTypesAl.size() + 1) { 3196 listWithDun = oldTypesAl; 3197 listWithoutDun = newTypesAl; 3198 dunInOld = true; 3199 } else if (oldTypesAl.size() + 1 == newTypesAl.size()) { 3200 listWithDun = newTypesAl; 3201 listWithoutDun = oldTypesAl; 3202 } else { 3203 return false; 3204 } 3205 3206 if (listWithDun.contains("dun") && !listWithoutDun.contains("dun")) { 3207 listWithoutDun.add("dun"); 3208 if (!listWithDun.containsAll(listWithoutDun)) { 3209 return false; 3210 } 3211 3212 // Only difference between old type and new type is that 3213 // one has dun 3214 // Check if profile_id is 0/not set 3215 if (oldRow.getInt(oldRow.getColumnIndex(PROFILE_ID)) == 0) { 3216 if (dunInOld) { 3217 // Update oldRow to remove dun from its type field 3218 ContentValues updateOldRow = new ContentValues(); 3219 StringBuilder sb = new StringBuilder(); 3220 boolean first = true; 3221 for (String s : listWithDun) { 3222 if (!s.equalsIgnoreCase("dun")) { 3223 sb.append(first ? s : "," + s); 3224 first = false; 3225 } 3226 } 3227 String updatedType = sb.toString(); 3228 if (VDBG) { 3229 log("separateRowsNeeded: updating type in oldRow to " + updatedType); 3230 } 3231 updateOldRow.put(TYPE, updatedType); 3232 db.update(table, updateOldRow, 3233 "_id=" + oldRow.getInt(oldRow.getColumnIndex("_id")), null); 3234 return true; 3235 } else { 3236 if (VDBG) log("separateRowsNeeded: adding profile id 1 to newRow"); 3237 // Update newRow to set profile_id to 1 3238 newRow.put(PROFILE_ID, new Integer(1)); 3239 } 3240 } else { 3241 return false; 3242 } 3243 3244 // If match was found, both oldRow and newRow need to exist 3245 // separately in db. Add newRow to db. 3246 try { 3247 db.insertWithOnConflict(table, null, newRow, SQLiteDatabase.CONFLICT_REPLACE); 3248 if (VDBG) log("separateRowsNeeded: added newRow with profile id 1 to db"); 3249 return true; 3250 } catch (SQLException e) { 3251 loge("Exception on trying to add new row after updating profile_id"); 3252 } 3253 } 3254 3255 return false; 3256 } 3257 selectConflictingRow(SQLiteDatabase db, String table, ContentValues row)3258 public static Cursor selectConflictingRow(SQLiteDatabase db, String table, 3259 ContentValues row) { 3260 // Conflict is possible only when numeric, mcc, mnc (fields without any default value) 3261 // are set in the new row 3262 if (!row.containsKey(NUMERIC) || !row.containsKey(MCC) || !row.containsKey(MNC)) { 3263 loge("dbh.selectConflictingRow: called for non-conflicting row: " + row); 3264 return null; 3265 } 3266 3267 String[] columns = { "_id", 3268 TYPE, 3269 EDITED_STATUS, 3270 BEARER_BITMASK, 3271 NETWORK_TYPE_BITMASK, 3272 PROFILE_ID }; 3273 String selection = TextUtils.join("=? AND ", CARRIERS_UNIQUE_FIELDS) + "=?"; 3274 int i = 0; 3275 String[] selectionArgs = new String[CARRIERS_UNIQUE_FIELDS.size()]; 3276 for (String field : CARRIERS_UNIQUE_FIELDS) { 3277 if (!row.containsKey(field)) { 3278 selectionArgs[i++] = CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(field); 3279 } else { 3280 if (CARRIERS_BOOLEAN_FIELDS.contains(field)) { 3281 // for boolean fields we overwrite the strings "true" and "false" with "1" 3282 // and "0" 3283 selectionArgs[i++] = convertStringToIntString(row.getAsString(field)); 3284 } else { 3285 selectionArgs[i++] = row.getAsString(field); 3286 } 3287 } 3288 } 3289 3290 Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null); 3291 3292 if (c != null) { 3293 if (c.getCount() == 1) { 3294 if (VDBG) log("dbh.selectConflictingRow: " + c.getCount() + " conflicting " + 3295 "row found"); 3296 if (c.moveToFirst()) { 3297 return c; 3298 } else { 3299 loge("dbh.selectConflictingRow: moveToFirst() failed"); 3300 } 3301 } else { 3302 loge("dbh.selectConflictingRow: Expected 1 but found " + c.getCount() + 3303 " matching rows found for cv " + row); 3304 } 3305 c.close(); 3306 } else { 3307 loge("dbh.selectConflictingRow: Error - c is null; no matching row found for " + 3308 "cv " + row); 3309 } 3310 3311 return null; 3312 } 3313 3314 /** 3315 * Convert "true" and "false" to "1" and "0". 3316 * If the passed in string is already "1" or "0" returns the passed in string. 3317 */ convertStringToIntString(String boolString)3318 private static String convertStringToIntString(String boolString) { 3319 if ("0".equals(boolString) || "false".equalsIgnoreCase(boolString)) return "0"; 3320 return "1"; 3321 } 3322 3323 /** 3324 * Convert "1" and "0" to "true" and "false". 3325 * If the passed in string is already "true" or "false" returns the passed in string. 3326 */ convertStringToBoolString(String intString)3327 private static String convertStringToBoolString(String intString) { 3328 if ("0".equals(intString) || "false".equalsIgnoreCase(intString)) return "false"; 3329 return "true"; 3330 } 3331 3332 /** 3333 * These methods can be overridden in a subclass for testing TelephonyProvider using an 3334 * in-memory database. 3335 */ getReadableDatabase()3336 SQLiteDatabase getReadableDatabase() { 3337 return mOpenHelper.getReadableDatabase(); 3338 } getWritableDatabase()3339 SQLiteDatabase getWritableDatabase() { 3340 return mOpenHelper.getWritableDatabase(); 3341 } initDatabaseWithDatabaseHelper(SQLiteDatabase db)3342 void initDatabaseWithDatabaseHelper(SQLiteDatabase db) { 3343 mOpenHelper.initDatabase(db); 3344 } needApnDbUpdate()3345 boolean needApnDbUpdate() { 3346 return mOpenHelper.apnDbUpdateNeeded(); 3347 } 3348 apnSourceServiceExists(Context context)3349 private static boolean apnSourceServiceExists(Context context) { 3350 if (s_apnSourceServiceExists != null) { 3351 return s_apnSourceServiceExists; 3352 } 3353 try { 3354 String service = context.getResources().getString(R.string.apn_source_service); 3355 if (TextUtils.isEmpty(service)) { 3356 s_apnSourceServiceExists = false; 3357 } else { 3358 s_apnSourceServiceExists = context.getPackageManager().getServiceInfo( 3359 ComponentName.unflattenFromString(service), 0) 3360 != null; 3361 } 3362 } catch (PackageManager.NameNotFoundException e) { 3363 s_apnSourceServiceExists = false; 3364 } 3365 return s_apnSourceServiceExists; 3366 } 3367 restoreApnsWithService(int subId)3368 private void restoreApnsWithService(int subId) { 3369 Context context = getContext(); 3370 Resources r = context.getResources(); 3371 AtomicBoolean connectionBindingInvalid = new AtomicBoolean(false); 3372 ServiceConnection connection = new ServiceConnection() { 3373 @Override 3374 public void onServiceConnected(ComponentName className, 3375 IBinder service) { 3376 log("restoreApnsWithService: onServiceConnected"); 3377 synchronized (mLock) { 3378 mIApnSourceService = IApnSourceService.Stub.asInterface(service); 3379 mLock.notifyAll(); 3380 } 3381 } 3382 3383 @Override 3384 public void onServiceDisconnected(ComponentName arg0) { 3385 loge("mIApnSourceService has disconnected unexpectedly"); 3386 synchronized (mLock) { 3387 mIApnSourceService = null; 3388 } 3389 } 3390 3391 @Override 3392 public void onBindingDied(ComponentName name) { 3393 loge("The binding to the apn service connection is dead: " + name); 3394 synchronized (mLock) { 3395 connectionBindingInvalid.set(true); 3396 mLock.notifyAll(); 3397 } 3398 } 3399 3400 @Override 3401 public void onNullBinding(ComponentName name) { 3402 loge("Null binding: " + name); 3403 synchronized (mLock) { 3404 connectionBindingInvalid.set(true); 3405 mLock.notifyAll(); 3406 } 3407 } 3408 }; 3409 3410 Intent intent = new Intent(IApnSourceService.class.getName()); 3411 intent.setComponent(ComponentName.unflattenFromString( 3412 r.getString(R.string.apn_source_service))); 3413 log("binding to service to restore apns, intent=" + intent); 3414 try { 3415 if (context.bindService(intent, 3416 Context.BIND_IMPORTANT | Context.BIND_AUTO_CREATE, 3417 runnable -> new Thread(runnable).start(), 3418 connection)) { 3419 synchronized (mLock) { 3420 while (mIApnSourceService == null && !connectionBindingInvalid.get()) { 3421 try { 3422 mLock.wait(); 3423 } catch (InterruptedException e) { 3424 loge("Error while waiting for service connection: " + e); 3425 } 3426 } 3427 if (connectionBindingInvalid.get()) { 3428 loge("The binding is invalid."); 3429 return; 3430 } 3431 try { 3432 ContentValues[] values = mIApnSourceService.getApns(subId); 3433 if (values != null) { 3434 // we use the unsynchronized insert because this function is called 3435 // within the syncrhonized function delete() 3436 unsynchronizedBulkInsert(CONTENT_URI, values); 3437 log("restoreApnsWithService: restored"); 3438 } 3439 } catch (RemoteException e) { 3440 loge("Error applying apns from service: " + e); 3441 } 3442 } 3443 } else { 3444 loge("unable to bind to service from intent=" + intent); 3445 } 3446 } catch (SecurityException e) { 3447 loge("Error applying apns from service: " + e); 3448 } finally { 3449 if (connection != null) { 3450 context.unbindService(connection); 3451 } 3452 synchronized (mLock) { 3453 mIApnSourceService = null; 3454 } 3455 } 3456 } 3457 3458 3459 @Override onCreate()3460 public boolean onCreate() { 3461 mOpenHelper = new DatabaseHelper(getContext()); 3462 mDefaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 3463 boolean isNewBuild = false; 3464 String newBuildId = SystemProperties.get("ro.build.id", null); 3465 SharedPreferences sp = getContext().getSharedPreferences(BUILD_ID_FILE, 3466 Context.MODE_PRIVATE); 3467 if (!TextUtils.isEmpty(newBuildId)) { 3468 // Check if build id has changed 3469 String oldBuildId = sp.getString(RO_BUILD_ID, ""); 3470 if (!newBuildId.equals(oldBuildId)) { 3471 localLog("onCreate: build id changed from " + oldBuildId + " to " + newBuildId); 3472 isNewBuild = true; 3473 } else { 3474 if (VDBG) log("onCreate: build id did not change: " + oldBuildId); 3475 } 3476 } else { 3477 if (VDBG) log("onCreate: newBuildId is empty"); 3478 } 3479 3480 if (isNewBuild) { 3481 if (!apnSourceServiceExists(getContext())) { 3482 // Update APN DB 3483 updateApnDb(); 3484 } 3485 3486 // Add all APN related shared prefs to local log for dumpsys 3487 if (DBG) addAllApnSharedPrefToLocalLog(); 3488 } 3489 3490 // Write build id to SharedPreferences after APNs have been updated above by updateApnDb() 3491 if (!TextUtils.isEmpty(newBuildId)) { 3492 if (isNewBuild) log("onCreate: updating build id to " + newBuildId); 3493 sp.edit().putString(RO_BUILD_ID, newBuildId).apply(); 3494 } 3495 3496 SharedPreferences spEnforcedFile = getContext().getSharedPreferences(ENFORCED_FILE, 3497 Context.MODE_PRIVATE); 3498 mManagedApnEnforced = spEnforcedFile.getBoolean(ENFORCED_KEY, false); 3499 3500 ProviderUtil.logRunningTelephonyProviderProcesses(getContext()); 3501 if (VDBG) log("onCreate:- ret true"); 3502 return true; 3503 } 3504 addAllApnSharedPrefToLocalLog()3505 private void addAllApnSharedPrefToLocalLog() { 3506 localLog("addAllApnSharedPrefToLocalLog"); 3507 SharedPreferences spApn = getContext().getSharedPreferences(PREF_FILE_APN, 3508 Context.MODE_PRIVATE); 3509 3510 Map<String, ?> allPrefApnId = spApn.getAll(); 3511 for (String key : allPrefApnId.keySet()) { 3512 try { 3513 localLog(key + ":" + allPrefApnId.get(key).toString()); 3514 } catch (Exception e) { 3515 localLog("Skipping over key " + key + " due to exception " + e); 3516 } 3517 } 3518 3519 SharedPreferences spFullApn = getContext().getSharedPreferences(PREF_FILE_FULL_APN, 3520 Context.MODE_PRIVATE); 3521 3522 Map<String, ?> allPrefFullApn = spFullApn.getAll(); 3523 for (String key : allPrefFullApn.keySet()) { 3524 try { 3525 localLog(key + ":" + allPrefFullApn.get(key).toString()); 3526 } catch (Exception e) { 3527 localLog("Skipping over key " + key + " due to exception " + e); 3528 } 3529 } 3530 } 3531 localLog(String logMsg)3532 private void localLog(String logMsg) { 3533 Log.d(TAG, logMsg); 3534 mLocalLog.log(logMsg); 3535 } 3536 isManagedApnEnforced()3537 private synchronized boolean isManagedApnEnforced() { 3538 return mManagedApnEnforced; 3539 } 3540 setManagedApnEnforced(boolean enforced)3541 private void setManagedApnEnforced(boolean enforced) { 3542 SharedPreferences sp = getContext().getSharedPreferences(ENFORCED_FILE, 3543 Context.MODE_PRIVATE); 3544 SharedPreferences.Editor editor = sp.edit(); 3545 editor.putBoolean(ENFORCED_KEY, enforced); 3546 editor.apply(); 3547 synchronized (this) { 3548 mManagedApnEnforced = enforced; 3549 } 3550 } 3551 setPreferredApnId(Long id, int subId, boolean saveApn)3552 private void setPreferredApnId(Long id, int subId, boolean saveApn) { 3553 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN, 3554 Context.MODE_PRIVATE); 3555 SharedPreferences.Editor editor = sp.edit(); 3556 editor.putLong(COLUMN_APN_ID + subId, id != null ? id : INVALID_APN_ID); 3557 localLog("setPreferredApnId: " + COLUMN_APN_ID + subId + ":" 3558 + (id != null ? id : INVALID_APN_ID)); 3559 // This is for debug purposes. It indicates if this APN was set by DcTracker or user (true) 3560 // or if this was restored from APN saved in PREF_FILE_FULL_APN (false). 3561 editor.putBoolean(EXPLICIT_SET_CALLED + subId, saveApn); 3562 localLog("setPreferredApnId: " + EXPLICIT_SET_CALLED + subId + ":" + saveApn); 3563 editor.apply(); 3564 if (id == null || id.longValue() == INVALID_APN_ID) { 3565 deletePreferredApn(subId); 3566 } else { 3567 // If id is not invalid, and saveApn is true, save the actual APN in PREF_FILE_FULL_APN 3568 // too. 3569 if (saveApn) { 3570 setPreferredApn(id, subId); 3571 } 3572 } 3573 } 3574 getPreferredApnId(int subId, boolean checkApnSp)3575 private long getPreferredApnId(int subId, boolean checkApnSp) { 3576 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN, 3577 Context.MODE_PRIVATE); 3578 long apnId = sp.getLong(COLUMN_APN_ID + subId, INVALID_APN_ID); 3579 if (apnId == INVALID_APN_ID && checkApnSp) { 3580 apnId = getPreferredApnIdFromApn(subId); 3581 if (apnId != INVALID_APN_ID) { 3582 setPreferredApnId(apnId, subId, false); 3583 } 3584 } 3585 return apnId; 3586 } 3587 getPreferredApnSetId(int subId)3588 private int getPreferredApnSetId(int subId) { 3589 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN, 3590 Context.MODE_PRIVATE); 3591 try { 3592 return Integer.parseInt(sp.getString(APN_SET_ID + subId, null)); 3593 } catch (NumberFormatException e) { 3594 return NO_APN_SET_ID; 3595 } 3596 } 3597 deletePreferredApnId(Context context)3598 private void deletePreferredApnId(Context context) { 3599 SharedPreferences sp = context.getSharedPreferences(PREF_FILE_APN, 3600 Context.MODE_PRIVATE); 3601 SharedPreferences.Editor editor = sp.edit(); 3602 editor.clear(); 3603 editor.apply(); 3604 } 3605 setPreferredApn(Long id, int subId)3606 private void setPreferredApn(Long id, int subId) { 3607 localLog("setPreferredApn: _id " + id + " subId " + subId); 3608 SQLiteDatabase db = getWritableDatabase(); 3609 // query all unique fields from id 3610 String[] proj = CARRIERS_UNIQUE_FIELDS.toArray(new String[CARRIERS_UNIQUE_FIELDS.size()]); 3611 3612 Cursor c = db.query(CARRIERS_TABLE, proj, "_id=" + id, null, null, null, null); 3613 if (c != null) { 3614 if (c.getCount() == 1) { 3615 c.moveToFirst(); 3616 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN, 3617 Context.MODE_PRIVATE); 3618 SharedPreferences.Editor editor = sp.edit(); 3619 // store values of all unique fields to SP 3620 for (String key : CARRIERS_UNIQUE_FIELDS) { 3621 editor.putString(key + subId, c.getString(c.getColumnIndex(key))); 3622 localLog("setPreferredApn: " + key + subId + ":" 3623 + c.getString(c.getColumnIndex(key))); 3624 } 3625 // also store the version number 3626 editor.putString(DB_VERSION_KEY + subId, "" + DATABASE_VERSION); 3627 localLog("setPreferredApn: " + DB_VERSION_KEY + subId + ":" + DATABASE_VERSION); 3628 editor.apply(); 3629 } else { 3630 log("setPreferredApn: # matching APNs found " + c.getCount()); 3631 } 3632 c.close(); 3633 } else { 3634 log("setPreferredApn: No matching APN found"); 3635 } 3636 } 3637 getPreferredApnIdFromApn(int subId)3638 private long getPreferredApnIdFromApn(int subId) { 3639 log("getPreferredApnIdFromApn: for subId " + subId); 3640 SQLiteDatabase db = getReadableDatabase(); 3641 3642 List<String> whereList = new ArrayList<>(); 3643 List<String> whereArgsList = new ArrayList<>(); 3644 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN, 3645 Context.MODE_PRIVATE); 3646 for (String key : CARRIERS_UNIQUE_FIELDS) { 3647 String value = sp.getString(key + subId, null); 3648 if (value == null) { 3649 continue; 3650 } else { 3651 whereList.add(key); 3652 whereArgsList.add(value); 3653 } 3654 } 3655 if (whereList.size() == 0) return INVALID_APN_ID; 3656 3657 String where = TextUtils.join("=? and ", whereList) + "=?"; 3658 String[] whereArgs = new String[whereArgsList.size()]; 3659 whereArgs = whereArgsList.toArray(whereArgs); 3660 3661 long apnId = INVALID_APN_ID; 3662 Cursor c = db.query(CARRIERS_TABLE, new String[]{"_id"}, where, whereArgs, null, null, 3663 null); 3664 if (c != null) { 3665 if (c.getCount() == 1) { 3666 c.moveToFirst(); 3667 apnId = c.getInt(c.getColumnIndex("_id")); 3668 } else { 3669 log("getPreferredApnIdFromApn: returning INVALID. # matching APNs found " + 3670 c.getCount()); 3671 } 3672 c.close(); 3673 } else { 3674 log("getPreferredApnIdFromApn: returning INVALID. No matching APN found"); 3675 } 3676 return apnId; 3677 } 3678 deletePreferredApn(int subId)3679 private void deletePreferredApn(int subId) { 3680 log("deletePreferredApn: for subId " + subId); 3681 SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN, 3682 Context.MODE_PRIVATE); 3683 if (sp.contains(DB_VERSION_KEY + subId)) { 3684 log("deletePreferredApn: apn is stored. Deleting it now for subId " + subId); 3685 SharedPreferences.Editor editor = sp.edit(); 3686 editor.remove(DB_VERSION_KEY + subId); 3687 for (String key : CARRIERS_UNIQUE_FIELDS) { 3688 editor.remove(key + subId); 3689 } 3690 editor.apply(); 3691 } 3692 } 3693 isCallingFromSystemOrPhoneUid()3694 boolean isCallingFromSystemOrPhoneUid() { 3695 int callingUid = mInjector.binderGetCallingUid(); 3696 return TelephonyPermissions.isSystemOrPhone(callingUid) 3697 // Allow ROOT for testing. ROOT can access underlying DB files anyways. 3698 || UserHandle.isSameApp(callingUid, Process.ROOT_UID); 3699 } 3700 ensureCallingFromSystemOrPhoneUid(String message)3701 void ensureCallingFromSystemOrPhoneUid(String message) { 3702 if (!isCallingFromSystemOrPhoneUid()) { 3703 throw new SecurityException(message); 3704 } 3705 } 3706 3707 @Override call(String method, @Nullable String args, @Nullable Bundle bundle)3708 public synchronized Bundle call(String method, @Nullable String args, @Nullable Bundle bundle) { 3709 if (SubscriptionManager.GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME.equals(method)) { 3710 getContext().enforceCallingOrSelfPermission( 3711 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, TAG); 3712 final long identity = Binder.clearCallingIdentity(); 3713 try { 3714 return retrieveSimSpecificSettings(); 3715 } finally { 3716 Binder.restoreCallingIdentity(identity); 3717 } 3718 } else if (SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME.equals(method)) { 3719 getContext().enforceCallingOrSelfPermission( 3720 android.Manifest.permission.MODIFY_PHONE_STATE, TAG); 3721 final long identity = Binder.clearCallingIdentity(); 3722 try { 3723 Bundle resultBundle = new Bundle(); 3724 boolean changed = restoreSimSpecificSettings(bundle, args); 3725 if (changed) { 3726 mLocalLog.log("Restoration changed the subscription database."); 3727 log("Restoration changed the subscription database."); 3728 } 3729 resultBundle.putBoolean( 3730 SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED, 3731 changed); 3732 return resultBundle; 3733 } finally { 3734 Binder.restoreCallingIdentity(identity); 3735 } 3736 } else { 3737 loge("method is not recognized"); 3738 } 3739 3740 return null; 3741 } 3742 3743 /** 3744 * See {@link SubscriptionController#GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME} for details 3745 */ retrieveSimSpecificSettings()3746 private Bundle retrieveSimSpecificSettings() { 3747 Bundle resultBundle = new Bundle(); 3748 resultBundle.putByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA, 3749 getSimSpecificDataToBackUp()); 3750 3751 return resultBundle; 3752 } 3753 3754 /** 3755 * Attempts to restore the backed up sim-specific configs to device. End result is SimInfoDB is 3756 * modified to match any backed up configs for the appropriate inserted sims. 3757 * 3758 * @param bundle containing the data to be restored. If {@code null}, then backed up 3759 * data should already be in internal storage and will be retrieved from there. 3760 * @param iccId of the SIM that a restore is being attempted for. If {@code null}, then try to 3761 * restore for all simInfo entries in SimInfoDB 3762 * 3763 * @return {@code true} if the restoration changed the subscription database. 3764 */ restoreSimSpecificSettings(@ullable Bundle bundle, @Nullable String iccId)3765 private boolean restoreSimSpecificSettings(@Nullable Bundle bundle, @Nullable String iccId) { 3766 int restoreCase = TelephonyProtoEnums.SIM_RESTORE_CASE_UNDEFINED_USE_CASE; 3767 if (bundle != null) { 3768 restoreCase = TelephonyProtoEnums.SIM_RESTORE_CASE_SUW; 3769 if (!writeSimSettingsToInternalStorage( 3770 bundle.getByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA))) { 3771 return false; 3772 } 3773 } else if (iccId != null){ 3774 restoreCase = TelephonyProtoEnums.SIM_RESTORE_CASE_SIM_INSERTED; 3775 } 3776 return mergeBackedUpDataToSimInfoDb(restoreCase, iccId); 3777 } 3778 3779 @VisibleForTesting writeSimSettingsToInternalStorage(byte[] data)3780 boolean writeSimSettingsToInternalStorage(byte[] data) { 3781 AtomicFile atomicFile = new AtomicFile( 3782 new File(getContext().getFilesDir(), BACKED_UP_SIM_SPECIFIC_SETTINGS_FILE)); 3783 FileOutputStream fos = null; 3784 try { 3785 fos = atomicFile.startWrite(); 3786 fos.write(data); 3787 atomicFile.finishWrite(fos); 3788 } catch (IOException e) { 3789 if (fos != null) { 3790 atomicFile.failWrite(fos); 3791 } 3792 loge("Not able to create internal file with per-sim configs. Failed with error " 3793 + e); 3794 return false; 3795 } 3796 3797 return true; 3798 } 3799 3800 /** 3801 * Attempt to match any SimInfoDB entries to what is in the internal backup data file and 3802 * update DB entry with the adequate backed up data. 3803 * 3804 * @param restoreCase one of the SimSpecificSettingsRestoreMatchingCriteria values defined in 3805 * frameworks/proto_logging/stats/enums/telephony/enums.proto 3806 * @param iccId of the SIM that a restore is being attempted for. If {@code null}, then try to 3807 * restore for all simInfo entries in SimInfoDB 3808 * 3809 * @return {@code true} if the restoration changed the subscription database. 3810 */ mergeBackedUpDataToSimInfoDb(int restoreCase, @Nullable String iccId)3811 private boolean mergeBackedUpDataToSimInfoDb(int restoreCase, @Nullable String iccId) { 3812 // Get data stored in internal file 3813 File file = new File(getContext().getFilesDir(), BACKED_UP_SIM_SPECIFIC_SETTINGS_FILE); 3814 if (!file.exists()) { 3815 loge("internal sim-specific settings backup data file does not exist. " 3816 + "Aborting restore"); 3817 return false; 3818 } 3819 3820 AtomicFile atomicFile = new AtomicFile(file); 3821 PersistableBundle bundle = null; 3822 try (FileInputStream fis = atomicFile.openRead()) { 3823 bundle = PersistableBundle.readFromStream(fis); 3824 } catch (IOException e) { 3825 loge("Failed to convert backed up per-sim configs to bundle. Stopping restore. " 3826 + "Failed with error " + e); 3827 return false; 3828 } 3829 3830 String selection = null; 3831 String[] selectionArgs = null; 3832 if (iccId != null) { 3833 selection = Telephony.SimInfo.COLUMN_ICC_ID + "=?"; 3834 selectionArgs = new String[]{iccId}; 3835 } 3836 try (Cursor cursor = query( 3837 SubscriptionManager.CONTENT_URI, 3838 new String[] { 3839 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, 3840 Telephony.SimInfo.COLUMN_ICC_ID, 3841 Telephony.SimInfo.COLUMN_NUMBER, 3842 Telephony.SimInfo.COLUMN_CARRIER_ID, 3843 Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE, 3844 Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 3845 }, 3846 selection, 3847 selectionArgs, 3848 ORDER_BY_SUB_ID)) { 3849 return findAndRestoreAllMatches(bundle.deepCopy(), cursor, restoreCase); 3850 } 3851 } 3852 3853 /** 3854 * Find the matched subscription and restore SIM specific settings to them. 3855 * 3856 * @param backedUpDataBundle The backed-up data to be restored. 3857 * @param cursor The database cursor. 3858 * @param restoreCase one of the SimSpecificSettingsRestoreMatchingCriteria values defined in 3859 * frameworks/proto_logging/stats/enums/telephony/enums.proto 3860 * 3861 * @return {@code true} if the restoration changed the subscription database. 3862 */ findAndRestoreAllMatches(PersistableBundle backedUpDataBundle, Cursor cursor, int restoreCase)3863 private boolean findAndRestoreAllMatches(PersistableBundle backedUpDataBundle, Cursor cursor, 3864 int restoreCase) { 3865 boolean changed = false; 3866 int[] previouslyRestoredSubIdsArray = 3867 backedUpDataBundle.getIntArray(KEY_PREVIOUSLY_RESTORED_SUB_IDS); 3868 List<Integer> previouslyRestoredSubIdsList = previouslyRestoredSubIdsArray != null 3869 ? Arrays.stream(previouslyRestoredSubIdsArray).boxed().collect(Collectors.toList()) 3870 : new ArrayList<>(); 3871 List<Integer> newlyRestoredSubIds = new ArrayList<>(); 3872 int backupDataFormatVersion = backedUpDataBundle 3873 .getInt(KEY_BACKUP_DATA_FORMAT_VERSION, -1); 3874 3875 Resources r = getContext().getResources(); 3876 List<String> wfcRestoreBlockedCountries = Arrays.asList(r.getStringArray( 3877 R.array.wfc_restore_blocked_countries)); 3878 3879 while (cursor != null && cursor.moveToNext()) { 3880 // Get all the possible matching criteria. 3881 int subIdColumnIndex = cursor.getColumnIndex( 3882 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID); 3883 int currSubIdFromDb = cursor.getInt(subIdColumnIndex); 3884 3885 if (previouslyRestoredSubIdsList.contains(currSubIdFromDb)) { 3886 // Abort restore for any sims that were previously restored. 3887 continue; 3888 } 3889 3890 int iccIdColumnIndex = cursor.getColumnIndex(Telephony.SimInfo.COLUMN_ICC_ID); 3891 String currIccIdFromDb = cursor.getString(iccIdColumnIndex); 3892 3893 int phoneNumberColumnIndex = cursor.getColumnIndex(Telephony.SimInfo.COLUMN_NUMBER); 3894 String currPhoneNumberFromDb = cursor.getString(phoneNumberColumnIndex); 3895 3896 int carrierIdColumnIndex = cursor.getColumnIndex(Telephony.SimInfo.COLUMN_CARRIER_ID); 3897 int currCarrierIdFromDb = cursor.getInt(carrierIdColumnIndex); 3898 3899 int isoCountryCodeColumnIndex = cursor.getColumnIndex( 3900 Telephony.SimInfo.COLUMN_ISO_COUNTRY_CODE); 3901 String isoCountryCodeFromDb = cursor.getString(isoCountryCodeColumnIndex); 3902 3903 int allowedNetworkTypesForReasonsIndex = cursor.getColumnIndex( 3904 Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS); 3905 String allowedNetworkTypesForReasonsFromDb = 3906 cursor.getString(allowedNetworkTypesForReasonsIndex); 3907 3908 // Find the best match from backed up data. 3909 SimRestoreMatch bestRestoreMatch = null; 3910 for (int rowNum = 0; true; rowNum++) { 3911 PersistableBundle currRow = backedUpDataBundle.getPersistableBundle( 3912 KEY_SIMINFO_DB_ROW_PREFIX + rowNum); 3913 if (currRow == null) { 3914 break; 3915 } 3916 3917 SimRestoreMatch currSimRestoreMatch = new SimRestoreMatch( 3918 currIccIdFromDb, currCarrierIdFromDb, currPhoneNumberFromDb, 3919 isoCountryCodeFromDb, allowedNetworkTypesForReasonsFromDb, 3920 wfcRestoreBlockedCountries, currRow, 3921 backupDataFormatVersion); 3922 3923 if (currSimRestoreMatch == null) { 3924 continue; 3925 } 3926 3927 /* 3928 * The three following match cases are ordered by descending priority: 3929 * - Match by iccId: If iccId of backup data matches iccId of any inserted sims, 3930 * we confidently restore all configs. 3931 * - Match phone number and carrierId: If both of these values match, we 3932 * confidently restore all configs. 3933 * - Match only carrierId: If only carrierId of backup data matches an inserted 3934 * sim, we only restore non-sensitive configs. 3935 * 3936 * Having a matchScore value for each match allows us to control these priorities. 3937 */ 3938 if (bestRestoreMatch == null || (currSimRestoreMatch.getMatchScore() 3939 >= bestRestoreMatch.getMatchScore() 3940 && currSimRestoreMatch.getContentValues() != null)) { 3941 bestRestoreMatch = currSimRestoreMatch; 3942 } 3943 } 3944 3945 if (bestRestoreMatch != null) { 3946 ContentValues newContentValues = bestRestoreMatch.getContentValues(); 3947 if (bestRestoreMatch.getMatchScore() != 0 && newContentValues != null) { 3948 if (restoreCase == TelephonyProtoEnums.SIM_RESTORE_CASE_SUW) { 3949 if (update(SubscriptionManager.SIM_INFO_SUW_RESTORE_CONTENT_URI, 3950 newContentValues, 3951 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?", 3952 new String[]{Integer.toString(currSubIdFromDb)}) > 0) { 3953 mLocalLog.log("Restored sub " + currSubIdFromDb + " from backup" 3954 + ". case=SUW"); 3955 log("Restored sub " + currSubIdFromDb + " from backup. case=SUW"); 3956 changed = true; 3957 } 3958 } else if (restoreCase == TelephonyProtoEnums.SIM_RESTORE_CASE_SIM_INSERTED) { 3959 Uri simInsertedRestoreUri = Uri.withAppendedPath( 3960 SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 3961 SIM_INSERTED_RESTORE_URI_SUFFIX); 3962 if (update(simInsertedRestoreUri, 3963 newContentValues, 3964 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?", 3965 new String[]{Integer.toString(currSubIdFromDb)}) > 0) { 3966 mLocalLog.log("Restored sub " + currSubIdFromDb + " from backup. " 3967 + "case=SIM inserted."); 3968 log("Restored sub " + currSubIdFromDb + " from backup. " 3969 + "case=SIM inserted."); 3970 changed = true; 3971 } 3972 } 3973 log("Restore of inserted SIM's sim-specific settings has been successfully " 3974 + "completed."); 3975 TelephonyStatsLog.write(TelephonyStatsLog.SIM_SPECIFIC_SETTINGS_RESTORED, 3976 TelephonyProtoEnums.SIM_RESTORE_RESULT_SUCCESS, 3977 restoreCase, bestRestoreMatch.getMatchingCriteriaForLogging()); 3978 newlyRestoredSubIds.add(currSubIdFromDb); 3979 } else { 3980 /* If this block was reached because ContentValues was null, that means the 3981 database schema was newer during backup than during restore. We consider this 3982 a no-match to avoid updating columns that don't exist */ 3983 TelephonyStatsLog.write(TelephonyStatsLog.SIM_SPECIFIC_SETTINGS_RESTORED, 3984 TelephonyProtoEnums.SIM_RESTORE_RESULT_NONE_MATCH, 3985 restoreCase, bestRestoreMatch.getMatchingCriteriaForLogging()); 3986 } 3987 } else { 3988 log("No matching SIM in backup data. SIM-specific settings not restored."); 3989 TelephonyStatsLog.write(TelephonyStatsLog.SIM_SPECIFIC_SETTINGS_RESTORED, 3990 TelephonyProtoEnums.SIM_RESTORE_RESULT_ZERO_SIM_IN_BACKUP, 3991 restoreCase, TelephonyProtoEnums.SIM_RESTORE_MATCHING_CRITERIA_NONE); 3992 } 3993 } 3994 3995 // Update the internal file with subIds that we just restored. 3996 previouslyRestoredSubIdsList.addAll(newlyRestoredSubIds); 3997 backedUpDataBundle.putIntArray( 3998 KEY_PREVIOUSLY_RESTORED_SUB_IDS, 3999 previouslyRestoredSubIdsList.stream().mapToInt(i -> i).toArray()); 4000 try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { 4001 backedUpDataBundle.writeToStream(outputStream); 4002 writeSimSettingsToInternalStorage(outputStream.toByteArray()); 4003 } catch (IOException e) { 4004 loge("Not able to convert SimInfoDB to byte array. Not storing which subIds were " 4005 + "restored"); 4006 } 4007 return changed; 4008 } 4009 4010 private static class SimRestoreMatch { 4011 4012 private Set<Integer> matches = new ArraySet<>(); 4013 private int subId; 4014 private ContentValues contentValues; 4015 private int matchingCriteria; 4016 private int matchScore; 4017 4018 private static final int ICCID_MATCH = 1; 4019 private static final int PHONE_NUMBER_MATCH = 2; 4020 private static final int CARRIER_ID_MATCH = 3; 4021 SimRestoreMatch(String iccIdFromDb, int carrierIdFromDb, String phoneNumberFromDb, String isoCountryCodeFromDb, String allowedNetworkTypesForReasonsFromDb, List<String> wfcRestoreBlockedCountries, PersistableBundle backedUpSimInfoEntry, int backupDataFormatVersion)4022 public SimRestoreMatch(String iccIdFromDb, int carrierIdFromDb, 4023 String phoneNumberFromDb, String isoCountryCodeFromDb, 4024 String allowedNetworkTypesForReasonsFromDb, 4025 List<String> wfcRestoreBlockedCountries, 4026 PersistableBundle backedUpSimInfoEntry, int backupDataFormatVersion) { 4027 subId = backedUpSimInfoEntry.getInt( 4028 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID, 4029 DEFAULT_INT_COLUMN_VALUE); 4030 String iccIdFromBackup = backedUpSimInfoEntry.getString(Telephony.SimInfo.COLUMN_ICC_ID, 4031 ""); 4032 String phoneNumberFromBackup = backedUpSimInfoEntry.getString( 4033 Telephony.SimInfo.COLUMN_NUMBER, ""); 4034 int carrierIdFromBackup = backedUpSimInfoEntry.getInt( 4035 Telephony.SimInfo.COLUMN_CARRIER_ID, 4036 TelephonyManager.UNKNOWN_CARRIER_ID); 4037 4038 4039 // find all matching fields 4040 if (iccIdFromDb != null && iccIdFromDb.equals(iccIdFromBackup) 4041 && !iccIdFromBackup.isEmpty()) { 4042 matches.add(ICCID_MATCH); 4043 } 4044 if (carrierIdFromDb == carrierIdFromBackup 4045 && carrierIdFromBackup != TelephonyManager.UNKNOWN_CARRIER_ID) { 4046 matches.add(CARRIER_ID_MATCH); 4047 } 4048 if (phoneNumberFromDb != null && phoneNumberFromDb.equals(phoneNumberFromBackup) 4049 && !phoneNumberFromBackup.isEmpty()) { 4050 matches.add(PHONE_NUMBER_MATCH); 4051 } 4052 4053 contentValues = convertBackedUpDataToContentValues( 4054 backedUpSimInfoEntry, backupDataFormatVersion, isoCountryCodeFromDb, 4055 allowedNetworkTypesForReasonsFromDb, wfcRestoreBlockedCountries); 4056 matchScore = calculateMatchScore(); 4057 matchingCriteria = calculateMatchingCriteria(); 4058 } 4059 getSubId()4060 public int getSubId() { 4061 return subId; 4062 } 4063 getContentValues()4064 public ContentValues getContentValues() { 4065 return contentValues; 4066 } 4067 getMatchScore()4068 public int getMatchScore() { 4069 return matchScore; 4070 } 4071 calculateMatchScore()4072 private int calculateMatchScore() { 4073 int score = 0; 4074 4075 if (matches.contains(ICCID_MATCH)) { 4076 score += 100; 4077 } 4078 if (matches.contains(CARRIER_ID_MATCH)) { 4079 if (matches.contains(PHONE_NUMBER_MATCH)) { 4080 score += 10; 4081 } else { 4082 score += 1; 4083 } 4084 } 4085 4086 return score; 4087 } 4088 getMatchingCriteriaForLogging()4089 public int getMatchingCriteriaForLogging() { 4090 return matchingCriteria; 4091 } 4092 calculateMatchingCriteria()4093 private int calculateMatchingCriteria() { 4094 if (matches.contains(ICCID_MATCH)) { 4095 return TelephonyProtoEnums.SIM_RESTORE_MATCHING_CRITERIA_ICCID; 4096 } 4097 if (matches.contains(CARRIER_ID_MATCH)) { 4098 if (matches.contains(PHONE_NUMBER_MATCH)) { 4099 return TelephonyProtoEnums 4100 .SIM_RESTORE_MATCHING_CRITERIA_CARRIER_ID_AND_PHONE_NUMBER; 4101 } else { 4102 return TelephonyProtoEnums.SIM_RESTORE_MATCHING_CRITERIA_CARRIER_ID_ONLY; 4103 } 4104 } 4105 return TelephonyProtoEnums.SIM_RESTORE_MATCHING_CRITERIA_NONE; 4106 } 4107 convertBackedUpDataToContentValues( PersistableBundle backedUpSimInfoEntry, int backupDataFormatVersion, String isoCountryCodeFromDb, String allowedNetworkTypesForReasonsFromDb, List<String> wfcRestoreBlockedCountries)4108 private ContentValues convertBackedUpDataToContentValues( 4109 PersistableBundle backedUpSimInfoEntry, int backupDataFormatVersion, 4110 String isoCountryCodeFromDb, String allowedNetworkTypesForReasonsFromDb, 4111 List<String> wfcRestoreBlockedCountries) { 4112 if (DATABASE_VERSION != 74 << 16) { 4113 throw new AssertionError("The database schema has been updated which might make " 4114 + "the format of #BACKED_UP_SIM_SPECIFIC_SETTINGS_FILE outdated. Make sure to " 4115 + "1) review whether any of the columns in #SIM_INFO_COLUMNS_TO_BACKUP have " 4116 + "been migrated or deleted, 2) add the new column name into one of those " 4117 + "maps, 3) add migration code in this method as necessary, and 4) update the " 4118 + "version check in this if statement."); 4119 } 4120 ContentValues contentValues = new ContentValues(); 4121 // Don't restore anything if restoring from a newer version of the current database. 4122 if (backupDataFormatVersion > DATABASE_VERSION) { 4123 return null; 4124 } 4125 4126 /* Any migration logic should be placed under this comment block. 4127 * ex: 4128 * if (backupDataFormatVersion >= 48 << 19) { 4129 * contentValues.put(NEW_COLUMN_NAME_2, 4130 * backedUpSimInfoEntry.getInt( OLD_COLUMN_NAME, DEFAULT_INT_COLUMN_VALUE)); 4131 * ... 4132 * } else if (backupDataFormatVersion >= 48 << 17) { 4133 * contentValues.put(NEW_COLUMN_NAME_1, 4134 * backedUpSimInfoEntry.getInt(OLD_COLUMN_NAME, DEFAULT_INT_COLUMN_VALUE)); 4135 * ... 4136 * } else { 4137 * // The values from the first format of backup ever available. 4138 * contentValues.put(Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 4139 * backedUpSimInfoEntry.getInt( 4140 * Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 4141 * DEFAULT_INT_COLUMN_VALUE)); 4142 * contentValues.put(Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 4143 * backedUpSimInfoEntry.getString( 4144 * Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, "")); 4145 * contentValues.put(Telephony.SimInfo.COLUMN_VT_IMS_ENABLED, 4146 * backedUpSimInfoEntry.getString(Telephony.SimInfo.COLUMN_VT_IMS_ENABLED, 4147 * "")); 4148 * ... 4149 * } 4150 * 4151 * Also make sure to add necessary removal of sensitive settings in 4152 * polishContentValues(ContentValues contentValues). 4153 */ 4154 if (backupDataFormatVersion >= 74 << 16) { 4155 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS, 4156 backedUpSimInfoEntry.getString( 4157 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS, 4158 DEFAULT_STRING_COLUMN_VALUE)); 4159 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS, 4160 backedUpSimInfoEntry.getString( 4161 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS, 4162 DEFAULT_STRING_COLUMN_VALUE)); 4163 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP, 4164 backedUpSimInfoEntry.getString( 4165 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP, 4166 DEFAULT_STRING_COLUMN_VALUE)); 4167 contentValues.put( 4168 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY, 4169 backedUpSimInfoEntry.getString( 4170 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY, 4171 DEFAULT_STRING_COLUMN_VALUE)); 4172 contentValues.put( 4173 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY, 4174 backedUpSimInfoEntry.getString( 4175 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY, 4176 DEFAULT_STRING_COLUMN_VALUE)); 4177 4178 } 4179 if (backupDataFormatVersion >= 73 << 16) { 4180 contentValues.put( 4181 Telephony.SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM, 4182 backedUpSimInfoEntry.getInt( 4183 Telephony.SimInfo 4184 .COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM, 4185 DEFAULT_INT_COLUMN_VALUE)); 4186 } 4187 if (backupDataFormatVersion >= 72 << 16) { 4188 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED, 4189 backedUpSimInfoEntry.getInt( 4190 Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED, 4191 DEFAULT_INT_COLUMN_VALUE)); 4192 } 4193 if (backupDataFormatVersion >= 71 << 16) { 4194 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, 4195 backedUpSimInfoEntry.getInt( 4196 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, 4197 DEFAULT_INT_COLUMN_VALUE)); 4198 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS, 4199 backedUpSimInfoEntry.getString( 4200 Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS, 4201 DEFAULT_STRING_COLUMN_VALUE)); 4202 contentValues.put(Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 4203 replaceEnable2g( 4204 allowedNetworkTypesForReasonsFromDb, 4205 backedUpSimInfoEntry.getString(Telephony.SimInfo 4206 .COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS), 4207 DEFAULT_STRING_COLUMN_VALUE)); 4208 } 4209 if (backupDataFormatVersion >= 70 << 16) { 4210 contentValues.put(Telephony.SimInfo.COLUMN_TRANSFER_STATUS, 4211 backedUpSimInfoEntry.getInt(Telephony.SimInfo.COLUMN_TRANSFER_STATUS, 4212 DEFAULT_INT_COLUMN_VALUE)); 4213 } 4214 if (backupDataFormatVersion >= 64 << 16) { 4215 contentValues.put(Telephony.SimInfo.COLUMN_IS_ONLY_NTN, 4216 backedUpSimInfoEntry.getInt(Telephony.SimInfo.COLUMN_IS_ONLY_NTN, 4217 DEFAULT_INT_COLUMN_VALUE)); 4218 } 4219 if (backupDataFormatVersion >= 63 << 16) { 4220 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 4221 backedUpSimInfoEntry.getInt( 4222 Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 4223 DEFAULT_INT_COLUMN_VALUE)); 4224 } 4225 if (backupDataFormatVersion >= 62 << 16) { 4226 contentValues.put(Telephony.SimInfo.COLUMN_SATELLITE_ENABLED, 4227 backedUpSimInfoEntry.getInt( 4228 Telephony.SimInfo.COLUMN_SATELLITE_ENABLED, 4229 DEFAULT_INT_COLUMN_VALUE)); 4230 } 4231 if (backupDataFormatVersion >= 60 << 16) { 4232 contentValues.put(Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, 4233 backedUpSimInfoEntry.getString( 4234 Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, 4235 DEFAULT_STRING_COLUMN_VALUE)); 4236 } 4237 if (backupDataFormatVersion >= 57 << 16) { 4238 contentValues.put(Telephony.SimInfo.COLUMN_USAGE_SETTING, 4239 backedUpSimInfoEntry.getInt( 4240 Telephony.SimInfo.COLUMN_USAGE_SETTING, 4241 DEFAULT_INT_COLUMN_VALUE)); 4242 } 4243 if (backupDataFormatVersion >= 52 << 16) { 4244 contentValues.put(Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, 4245 backedUpSimInfoEntry.getInt( 4246 Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, 4247 DEFAULT_INT_COLUMN_VALUE)); 4248 } 4249 if (backupDataFormatVersion >= 51 << 16) { 4250 contentValues.put(Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 4251 backedUpSimInfoEntry.getString( 4252 Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 4253 DEFAULT_STRING_COLUMN_VALUE)); 4254 } 4255 if (backupDataFormatVersion >= 50 << 16) { 4256 contentValues.put(Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING, 4257 backedUpSimInfoEntry.getInt( 4258 Telephony.SimInfo.COLUMN_D2D_STATUS_SHARING, 4259 DEFAULT_INT_COLUMN_VALUE)); 4260 } 4261 contentValues.put(Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 4262 backedUpSimInfoEntry.getInt( 4263 Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 4264 DEFAULT_INT_COLUMN_VALUE)); 4265 contentValues.put(Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 4266 backedUpSimInfoEntry.getInt( 4267 Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 4268 DEFAULT_INT_COLUMN_VALUE)); 4269 contentValues.put(Telephony.SimInfo.COLUMN_VT_IMS_ENABLED, 4270 backedUpSimInfoEntry.getInt( 4271 Telephony.SimInfo.COLUMN_VT_IMS_ENABLED, 4272 DEFAULT_INT_COLUMN_VALUE)); 4273 if (isoCountryCodeFromDb != null 4274 && !wfcRestoreBlockedCountries 4275 .contains(isoCountryCodeFromDb.toLowerCase(Locale.ROOT))) { 4276 // Don't restore COLUMN_WFC_IMS_ENABLED if the sim is from one of the countries that 4277 // requires WFC entitlement. 4278 contentValues.put(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, 4279 backedUpSimInfoEntry.getInt( 4280 Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED, 4281 DEFAULT_INT_COLUMN_VALUE)); 4282 } 4283 contentValues.put(Telephony.SimInfo.COLUMN_WFC_IMS_MODE, 4284 backedUpSimInfoEntry.getInt( 4285 Telephony.SimInfo.COLUMN_WFC_IMS_MODE, 4286 DEFAULT_INT_COLUMN_VALUE)); 4287 contentValues.put(Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, 4288 backedUpSimInfoEntry.getInt( 4289 Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, 4290 DEFAULT_INT_COLUMN_VALUE)); 4291 4292 return polishContentValues(contentValues); 4293 } 4294 4295 /** 4296 * Replaces the value of the "enable_2g" key-value pair in the given input string with the 4297 * new "enable_2g key-value provided. 4298 * 4299 * @param input The input string to modify. 4300 * @param newEnable2g The new value for the "enable_2g" key-value pair. 4301 * @param defaultValue default value to return if replacement is not possible. 4302 * @return The modified input string with the updated "enable_2g" value. 4303 */ replaceEnable2g( @ullable String input, @Nullable String newEnable2g, String defaultValue)4304 private static @Nullable String replaceEnable2g( 4305 @Nullable String input, @Nullable String newEnable2g, String defaultValue) { 4306 if (newEnable2g == null 4307 || !newEnable2g.startsWith(ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G)) { 4308 return defaultValue; 4309 } else if (input == null || input.isBlank()) { 4310 return newEnable2g; 4311 } 4312 4313 String delimiter = ","; 4314 String[] parts = input.trim().split(delimiter); 4315 4316 // Finding and replacing the "enable_2g" value 4317 for (int i = 0; i < parts.length; i++) { 4318 if (parts[i].startsWith(ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G)) { 4319 parts[i] = newEnable2g; 4320 return String.join(delimiter, parts); 4321 } 4322 } 4323 4324 // Adding the "enable_2g" value if not found 4325 if (parts.length == 0) { 4326 return newEnable2g; 4327 } 4328 return input + "," + newEnable2g; 4329 } 4330 polishContentValues(ContentValues contentValues)4331 private ContentValues polishContentValues(ContentValues contentValues) { 4332 /* Remove any values that weren't found in the backup file. These were set to defaults 4333 in #convertBackedUpDataToContentValues(). */ 4334 for (Map.Entry<String, Integer> column : SIM_INFO_COLUMNS_TO_BACKUP.entrySet()) { 4335 String columnName = column.getKey(); 4336 4337 if (!contentValues.containsKey(columnName)) { 4338 continue; 4339 } 4340 4341 int columnType = column.getValue(); 4342 if (columnType == Cursor.FIELD_TYPE_INTEGER 4343 && DEFAULT_INT_COLUMN_VALUE == contentValues.getAsInteger(columnName)) { 4344 contentValues.remove(columnName); 4345 } else if (columnType == Cursor.FIELD_TYPE_STRING && contentValues 4346 .getAsString(columnName).equals(DEFAULT_STRING_COLUMN_VALUE)) { 4347 contentValues.remove(columnName); 4348 } 4349 } 4350 4351 if (matches.contains(ICCID_MATCH)) { 4352 return contentValues; 4353 } else if (matches.contains(CARRIER_ID_MATCH)) { 4354 if (!matches.contains(PHONE_NUMBER_MATCH)) { 4355 // Low confidence match should not restore sensitive configs. 4356 if (contentValues.containsKey(Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED)) { 4357 contentValues.remove(Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED); 4358 } 4359 } 4360 return contentValues; 4361 } 4362 return null; 4363 } 4364 4365 } 4366 4367 /** 4368 * Retrieves data from all columns in SimInfoDB of backup/restore interest. 4369 * 4370 * @return data of interest from SimInfoDB as a byte array. 4371 */ getSimSpecificDataToBackUp()4372 private byte[] getSimSpecificDataToBackUp() { 4373 Map<String, Integer> simInfoColumnsToBackup = SIM_INFO_COLUMNS_TO_BACKUP; 4374 String[] projection = simInfoColumnsToBackup.keySet() 4375 .toArray(new String[simInfoColumnsToBackup.size()]); 4376 4377 try (Cursor cursor = query(SubscriptionManager.CONTENT_URI, projection, null, null, null); 4378 ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { 4379 PersistableBundle topLevelBundle = new PersistableBundle(); 4380 topLevelBundle.putInt(KEY_BACKUP_DATA_FORMAT_VERSION, DATABASE_VERSION); 4381 for (int rowNum = 0; cursor != null && cursor.moveToNext(); rowNum++) { 4382 PersistableBundle rowBundle = convertSimInfoDbEntryToPersistableBundle(cursor); 4383 topLevelBundle.putPersistableBundle(KEY_SIMINFO_DB_ROW_PREFIX + rowNum, rowBundle); 4384 } 4385 topLevelBundle.writeToStream(outputStream); 4386 return outputStream.toByteArray(); 4387 } catch (IOException e) { 4388 loge("Not able to convert SimInfoDB to byte array. Returning empty byte array"); 4389 return new byte[0]; 4390 } 4391 } 4392 convertSimInfoDbEntryToPersistableBundle(Cursor cursor)4393 private static PersistableBundle convertSimInfoDbEntryToPersistableBundle(Cursor cursor) { 4394 PersistableBundle bundle = new PersistableBundle(); 4395 for (Map.Entry<String, Integer> column : SIM_INFO_COLUMNS_TO_BACKUP.entrySet()) { 4396 String columnName = column.getKey(); 4397 int columnType = column.getValue(); 4398 int columnIndex = cursor.getColumnIndex(columnName); 4399 if (Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS 4400 .equals(columnName)) { 4401 bundle.putString(columnName, 4402 filteredAllowedNetworkTypesForBackup(cursor.getString(columnIndex))); 4403 } else if (columnType == Cursor.FIELD_TYPE_INTEGER) { 4404 bundle.putInt(columnName, cursor.getInt(columnIndex)); 4405 } else if (columnType == Cursor.FIELD_TYPE_STRING) { 4406 bundle.putString(columnName, cursor.getString(columnIndex)); 4407 } else { 4408 throw new AssertionError("SimInfoDB column to be backed up is not recognized. Make " 4409 + "sure to properly add the desired colum name and value type to " 4410 + "SIM_INFO_COLUMNS_TO_BACKUP."); 4411 } 4412 } 4413 4414 return bundle; 4415 } 4416 4417 /** 4418 * Returns filtered allowed network types for backup. 4419 * 4420 * Filters and returns only {@link TelephonyManager#ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G} for 4421 * the TelephonyProvider column value for network types allowed with all reasons. 4422 * 4423 * @param networkTypeValues String Value for network types allowed with all reasons 4424 * @return String of "enable_2g=VALUE" format. if no reasons to backup returns null. 4425 */ filteredAllowedNetworkTypesForBackup(String networkTypeValues)4426 private static String filteredAllowedNetworkTypesForBackup(String networkTypeValues) { 4427 return networkTypeValues == null ? null : 4428 Arrays.stream(networkTypeValues.trim().split(",")) 4429 .filter(r -> r.startsWith(ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G)) 4430 .findFirst() 4431 .orElse(null); 4432 } 4433 4434 @Override query(Uri url, String[] projectionIn, String selection, String[] selectionArgs, String sort)4435 public Cursor query(Uri url, String[] projectionIn, String selection, String[] selectionArgs, 4436 String sort) { 4437 if (VDBG) log("query: url=" + url + ", projectionIn=" + Arrays.toString(projectionIn) 4438 + ", selection=" + selection + "selectionArgs=" + Arrays.toString(selectionArgs) 4439 + ", sort=" + sort); 4440 int match = s_urlMatcher.match(url); 4441 checkPermissionCompat(match, projectionIn); 4442 4443 mDefaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 4444 return queryInternal(url, projectionIn, selection, selectionArgs, sort); 4445 } 4446 4447 /** 4448 * Internally queries the database. 4449 * 4450 * Things to keep in mind when writing code for this function: 4451 * - Must be wrapped in synchronized before quering database. 4452 * - Please call external APIs, that use locks, outside of synchronized. 4453 */ queryInternal(Uri url, String[] projectionIn, String selection, String[] selectionArgs, String sort)4454 private Cursor queryInternal(Uri url, String[] projectionIn, String selection, 4455 String[] selectionArgs, String sort) { 4456 int subId = mDefaultSubId; 4457 String subIdString; 4458 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 4459 qb.setStrict(true); // a little protection from injection attacks 4460 qb.setTables(CARRIERS_TABLE); 4461 4462 List<String> constraints = new ArrayList<String>(); 4463 4464 int match = s_urlMatcher.match(url); 4465 switch (match) { 4466 case URL_TELEPHONY_USING_SUBID: { 4467 // The behaves exactly same as URL_SIM_APN_LIST_ID. 4468 subIdString = url.getLastPathSegment(); 4469 try { 4470 subId = Integer.parseInt(subIdString); 4471 } catch (NumberFormatException e) { 4472 loge("NumberFormatException" + e); 4473 return null; 4474 } 4475 qb.appendWhereStandalone(IS_NOT_OWNED_BY_DPC); 4476 return getSubscriptionMatchingAPNList(qb, projectionIn, selection, selectionArgs, 4477 sort, subId); 4478 4479 // TODO b/74213956 turn this back on once insertion includes correct sub id 4480 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString); 4481 } 4482 case URL_TELEPHONY: { 4483 constraints.add(IS_NOT_OWNED_BY_DPC); 4484 break; 4485 } 4486 4487 case URL_CURRENT_USING_SUBID: { 4488 subIdString = url.getLastPathSegment(); 4489 try { 4490 subId = Integer.parseInt(subIdString); 4491 } catch (NumberFormatException e) { 4492 loge("NumberFormatException" + e); 4493 return null; 4494 } 4495 // TODO b/74213956 turn this back on once insertion includes correct sub id 4496 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString); 4497 } 4498 //intentional fall through from above case 4499 case URL_CURRENT: { 4500 constraints.add("current IS NOT NULL"); 4501 constraints.add(IS_NOT_OWNED_BY_DPC); 4502 // do not ignore the selection since MMS may use it. 4503 //selection = null; 4504 break; 4505 } 4506 4507 case URL_ID: { 4508 constraints.add("_id = " + url.getPathSegments().get(1)); 4509 constraints.add(IS_NOT_OWNED_BY_DPC); 4510 break; 4511 } 4512 4513 case URL_PREFERAPN_USING_SUBID: 4514 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: { 4515 subIdString = url.getLastPathSegment(); 4516 try { 4517 subId = Integer.parseInt(subIdString); 4518 } catch (NumberFormatException e) { 4519 loge("NumberFormatException" + e); 4520 return null; 4521 } 4522 // TODO b/74213956 turn this back on once insertion includes correct sub id 4523 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString); 4524 } 4525 //intentional fall through from above case 4526 case URL_PREFERAPN: 4527 case URL_PREFERAPN_NO_UPDATE: { 4528 constraints.add("_id = " + getPreferredApnId(subId, true)); 4529 break; 4530 } 4531 4532 case URL_PREFERAPNSET_USING_SUBID: { 4533 subIdString = url.getLastPathSegment(); 4534 try { 4535 subId = Integer.parseInt(subIdString); 4536 } catch (NumberFormatException e) { 4537 loge("NumberFormatException" + e); 4538 return null; 4539 } 4540 // TODO b/74213956 turn this back on once insertion includes correct sub id 4541 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString); 4542 } 4543 // intentional fall through from above case 4544 case URL_PREFERAPNSET: { 4545 final int set = getPreferredApnSetId(subId); 4546 if (set == NO_APN_SET_ID) { 4547 return null; 4548 } 4549 constraints.add(APN_SET_ID + "=" + set); 4550 qb.appendWhere(TextUtils.join(" AND ", constraints)); 4551 return getSubscriptionMatchingAPNList(qb, projectionIn, selection, selectionArgs, 4552 sort, subId); 4553 } 4554 4555 case URL_DPC: { 4556 ensureCallingFromSystemOrPhoneUid("URL_DPC called from non SYSTEM_UID."); 4557 // DPC query only returns DPC records. 4558 constraints.add(IS_OWNED_BY_DPC); 4559 break; 4560 } 4561 4562 case URL_DPC_ID: { 4563 constraints.add("_id = " + url.getLastPathSegment()); 4564 ensureCallingFromSystemOrPhoneUid("URL_DPC called from non SYSTEM_UID."); 4565 // DPC query only returns DPC records. 4566 constraints.add(IS_OWNED_BY_DPC); 4567 break; 4568 } 4569 4570 case URL_FILTERED_ID: 4571 case URL_FILTERED_USING_SUBID: { 4572 String idString = url.getLastPathSegment(); 4573 if (match == URL_FILTERED_ID) { 4574 constraints.add("_id = " + idString); 4575 } else { 4576 try { 4577 subId = Integer.parseInt(idString); 4578 // TODO b/74213956 turn this back on once insertion includes correct sub id 4579 // constraints.add(SUBSCRIPTION_ID + "=" + subIdString); 4580 } catch (NumberFormatException e) { 4581 loge("NumberFormatException" + e); 4582 return null; 4583 } 4584 } 4585 } 4586 //intentional fall through from above case 4587 case URL_FILTERED: { 4588 if (isManagedApnEnforced()) { 4589 // If enforced, return DPC records only. 4590 constraints.add(IS_OWNED_BY_DPC); 4591 } else { 4592 // Otherwise return non-DPC records only. 4593 constraints.add(IS_NOT_OWNED_BY_DPC); 4594 } 4595 break; 4596 } 4597 4598 case URL_ENFORCE_MANAGED: { 4599 ensureCallingFromSystemOrPhoneUid( 4600 "URL_ENFORCE_MANAGED called from non SYSTEM_UID."); 4601 MatrixCursor cursor = new MatrixCursor(new String[]{ENFORCED_KEY}); 4602 cursor.addRow(new Object[]{isManagedApnEnforced() ? 1 : 0}); 4603 return cursor; 4604 } 4605 4606 case URL_SIMINFO: { 4607 qb.setTables(SIMINFO_TABLE); 4608 break; 4609 } 4610 case URL_SIM_APN_LIST_ID: { 4611 subIdString = url.getLastPathSegment(); 4612 try { 4613 subId = Integer.parseInt(subIdString); 4614 } catch (NumberFormatException e) { 4615 loge("NumberFormatException" + e); 4616 return null; 4617 } 4618 } 4619 //intentional fall through from above case 4620 case URL_SIM_APN_LIST: { 4621 qb.appendWhere(IS_NOT_OWNED_BY_DPC); 4622 return getSubscriptionMatchingAPNList(qb, projectionIn, selection, selectionArgs, 4623 sort, subId); 4624 } 4625 4626 case URL_SIM_APN_LIST_FILTERED_ID: { 4627 subIdString = url.getLastPathSegment(); 4628 try { 4629 subId = Integer.parseInt(subIdString); 4630 } catch (NumberFormatException e) { 4631 loge("NumberFormatException" + e); 4632 return null; 4633 } 4634 } 4635 //intentional fall through from above case 4636 case URL_SIM_APN_LIST_FILTERED: { 4637 if (isManagedApnEnforced()) { 4638 // If enforced, return DPC records only. 4639 qb.appendWhereStandalone(IS_OWNED_BY_DPC); 4640 } else { 4641 // Otherwise return non-DPC records only. 4642 qb.appendWhereStandalone(IS_NOT_OWNED_BY_DPC); 4643 } 4644 return getSubscriptionMatchingAPNList(qb, projectionIn, selection, selectionArgs, 4645 sort, subId); 4646 } 4647 4648 default: { 4649 return null; 4650 } 4651 } 4652 4653 // appendWhere doesn't add ANDs so we do it ourselves 4654 if (constraints.size() > 0) { 4655 qb.appendWhere(TextUtils.join(" AND ", constraints)); 4656 } 4657 4658 synchronized (this) { 4659 SQLiteDatabase db = getReadableDatabase(); 4660 Cursor ret = null; 4661 try { 4662 // Exclude entries marked deleted 4663 if (CARRIERS_TABLE.equals(qb.getTables())) { 4664 if (TextUtils.isEmpty(selection)) { 4665 selection = ""; 4666 } else { 4667 selection += " and "; 4668 } 4669 selection += IS_NOT_USER_DELETED + " and " 4670 + IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML + " and " 4671 + IS_NOT_CARRIER_DELETED + " and " 4672 + IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML; 4673 if (VDBG) log("query: selection modified to " + selection); 4674 } 4675 ret = qb.query(db, projectionIn, selection, selectionArgs, null, null, sort); 4676 } catch (SQLException e) { 4677 loge("got exception when querying: " + e); 4678 } 4679 if (ret != null) { 4680 ret.setNotificationUri(getContext().getContentResolver(), url); 4681 } 4682 return ret; 4683 } 4684 } 4685 4686 /** 4687 * This method syncs PREF_FILE_FULL_APN with the db based on the current preferred apn ids. 4688 */ updatePreferredApns()4689 private void updatePreferredApns() { 4690 SharedPreferences spApn = getContext().getSharedPreferences(PREF_FILE_APN, 4691 Context.MODE_PRIVATE); 4692 4693 Map<String, ?> allPrefApnId = spApn.getAll(); 4694 for (String key : allPrefApnId.keySet()) { 4695 if (key.startsWith(COLUMN_APN_ID)) { 4696 int subId; 4697 try { 4698 subId = Integer.parseInt(key.substring(COLUMN_APN_ID.length())); 4699 } catch (NumberFormatException e) { 4700 loge("updatePreferredApns: NumberFormatException for key=" + key); 4701 continue; 4702 } 4703 long preferredApnId = getPreferredApnId(subId, false); 4704 if (preferredApnId != INVALID_APN_ID) { 4705 setPreferredApn(preferredApnId, subId); 4706 } 4707 } 4708 } 4709 } 4710 4711 /** 4712 * To find the current sim APN. Query APN based on {MCC, MNC, MVNO} and {Carrier_ID}. 4713 * 4714 * There has three steps: 4715 * 1. Query the APN based on { MCC, MNC, MVNO } and if has results jump to step 3, else jump to 4716 * step 2. 4717 * 2. Fallback to query the parent APN that query based on { MCC, MNC }. 4718 * 3. Append the result with the APN that query based on { Carrier_ID } 4719 */ getSubscriptionMatchingAPNList(SQLiteQueryBuilder qb, String[] projectionIn, String selection, String[] selectionArgs, String sort, int subId)4720 private Cursor getSubscriptionMatchingAPNList(SQLiteQueryBuilder qb, String[] projectionIn, 4721 String selection, String[] selectionArgs, String sort, int subId) { 4722 Context context = getContext(); 4723 4724 // The SubscriptionManager can use the lock to query tables such as sim_info again, so 4725 // calling subscriptionManager should be performed outside of synchronized. 4726 final SubscriptionManager subscriptionManager = (SubscriptionManager) context 4727 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 4728 if (!subscriptionManager.isActiveSubscriptionId(subId)) { 4729 return null; 4730 } 4731 4732 return getSubscriptionMatchingAPNListSynchronized(qb, projectionIn, selection, 4733 selectionArgs, sort, subId); 4734 } 4735 getSubscriptionMatchingAPNListSynchronized( SQLiteQueryBuilder qb, String[] projectionIn, String selection, String[] selectionArgs, String sort, int subId)4736 private synchronized Cursor getSubscriptionMatchingAPNListSynchronized( 4737 SQLiteQueryBuilder qb, String[] projectionIn, String selection, String[] selectionArgs, 4738 String sort, int subId) { 4739 Cursor ret; 4740 Context context = getContext(); 4741 final TelephonyManager tm = ((TelephonyManager) context 4742 .getSystemService(Context.TELEPHONY_SERVICE)) 4743 .createForSubscriptionId(subId); 4744 SQLiteDatabase db = getReadableDatabase(); 4745 String mccmnc = tm.getSimOperator(); 4746 int carrierId = tm.getSimSpecificCarrierId(); 4747 4748 qb.appendWhereStandalone(IS_NOT_USER_DELETED + " and " + 4749 IS_NOT_USER_DELETED_BUT_PRESENT_IN_XML + " and " + 4750 IS_NOT_CARRIER_DELETED + " and " + 4751 IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML); 4752 4753 // For query db one time, append all conditions in one selection and separate results after 4754 // the query is completed. IMSI has special match rule, so just query the MCC / MNC and 4755 // filter the MVNO by ourselves 4756 qb.appendWhereStandalone(NUMERIC + " = '" + mccmnc + "' OR " + 4757 CARRIER_ID + " = '" + carrierId + "'"); 4758 4759 ret = qb.query(db, null, selection, selectionArgs, null, null, sort); 4760 if (ret == null) { 4761 loge("subId:" + subId + " query current APN but cursor is null."); 4762 return null; 4763 } 4764 4765 if (DBG) log("subId:" + subId + " mccmnc=" + mccmnc + " carrierId=" + carrierId + 4766 ", match current APN size: " + ret.getCount()); 4767 4768 String[] columnNames = projectionIn != null ? projectionIn : ret.getColumnNames(); 4769 MatrixCursor currentCursor = new MatrixCursor(columnNames); 4770 MatrixCursor parentCursor = new MatrixCursor(columnNames); 4771 MatrixCursor carrierIdCursor = new MatrixCursor(columnNames); 4772 MatrixCursor carrierIdNonMatchingMNOCursor = new MatrixCursor(columnNames); 4773 4774 int numericIndex = ret.getColumnIndex(NUMERIC); 4775 int mvnoIndex = ret.getColumnIndex(MVNO_TYPE); 4776 int mvnoDataIndex = ret.getColumnIndex(MVNO_MATCH_DATA); 4777 int carrierIdIndex = ret.getColumnIndex(CARRIER_ID); 4778 4779 // Separate the result into MatrixCursor 4780 while (ret.moveToNext()) { 4781 List<String> data = new ArrayList<>(); 4782 for (String column : columnNames) { 4783 data.add(ret.getString(ret.getColumnIndex(column))); 4784 } 4785 4786 boolean isCurrentSimOperator = false; 4787 if (!TextUtils.isEmpty(ret.getString(numericIndex))) { 4788 final long identity = Binder.clearCallingIdentity(); 4789 try { 4790 isCurrentSimOperator = tm.matchesCurrentSimOperator( 4791 ret.getString(numericIndex), 4792 getMvnoTypeIntFromString(ret.getString(mvnoIndex)), 4793 ret.getString(mvnoDataIndex)); 4794 } finally { 4795 Binder.restoreCallingIdentity(identity); 4796 } 4797 } 4798 4799 boolean isMVNOAPN = !TextUtils.isEmpty(ret.getString(numericIndex)) 4800 && isCurrentSimOperator; 4801 boolean isMNOAPN = !TextUtils.isEmpty(ret.getString(numericIndex)) 4802 && ret.getString(numericIndex).equals(mccmnc) 4803 && TextUtils.isEmpty(ret.getString(mvnoIndex)); 4804 boolean isCarrierIdAPN = !TextUtils.isEmpty(ret.getString(carrierIdIndex)) 4805 && ret.getString(carrierIdIndex).equals(String.valueOf(carrierId)) 4806 && carrierId != TelephonyManager.UNKNOWN_CARRIER_ID; 4807 4808 if (isMVNOAPN) { 4809 // 1. The APN that query based on legacy SIM MCC/MCC and MVNO 4810 currentCursor.addRow(data); 4811 } else if (isMNOAPN) { 4812 // 2. The APN that query based on SIM MCC/MNC 4813 parentCursor.addRow(data); 4814 } else if (isCarrierIdAPN) { 4815 // The APN that query based on carrier Id (not include the MVNO or MNO APN) 4816 if (TextUtils.isEmpty(ret.getString(numericIndex))) { 4817 carrierIdCursor.addRow(data); 4818 } else { 4819 carrierIdNonMatchingMNOCursor.addRow(data); 4820 } 4821 } 4822 } 4823 ret.close(); 4824 4825 MatrixCursor result; 4826 if (currentCursor.getCount() > 0) { 4827 if (DBG) log("match MVNO APN: " + currentCursor.getCount()); 4828 result = currentCursor; 4829 } else if (parentCursor.getCount() > 0) { 4830 if (DBG) log("match MNO APN: " + parentCursor.getCount()); 4831 result = parentCursor; 4832 } else { 4833 if (DBG) { 4834 log("No MVNO, MNO and no MCC/MNC match, but we have match/matches with the " + 4835 "same carrier id, count: " + carrierIdNonMatchingMNOCursor.getCount()); 4836 } 4837 result = carrierIdNonMatchingMNOCursor; 4838 } 4839 4840 if (DBG) log("match carrier id APN: " + carrierIdCursor.getCount()); 4841 appendCursorData(result, carrierIdCursor); 4842 return result; 4843 } 4844 appendCursorData(@onNull MatrixCursor from, @NonNull MatrixCursor to)4845 private static void appendCursorData(@NonNull MatrixCursor from, @NonNull MatrixCursor to) { 4846 while (to.moveToNext()) { 4847 List<Object> data = new ArrayList<>(); 4848 for (String column : to.getColumnNames()) { 4849 int index = to.getColumnIndex(column); 4850 switch (to.getType(index)) { 4851 case Cursor.FIELD_TYPE_INTEGER: 4852 data.add(to.getInt(index)); 4853 break; 4854 case Cursor.FIELD_TYPE_FLOAT: 4855 data.add(to.getFloat(index)); 4856 break; 4857 case Cursor.FIELD_TYPE_BLOB: 4858 data.add(to.getBlob(index)); 4859 break; 4860 case Cursor.FIELD_TYPE_STRING: 4861 case Cursor.FIELD_TYPE_NULL: 4862 data.add(to.getString(index)); 4863 break; 4864 } 4865 } 4866 from.addRow(data); 4867 } 4868 } 4869 4870 @Override getType(Uri url)4871 public String getType(Uri url) 4872 { 4873 switch (s_urlMatcher.match(url)) { 4874 case URL_TELEPHONY: 4875 case URL_TELEPHONY_USING_SUBID: 4876 return "vnd.android.cursor.dir/telephony-carrier"; 4877 4878 case URL_ID: 4879 case URL_FILTERED_ID: 4880 case URL_FILTERED_USING_SUBID: 4881 return "vnd.android.cursor.item/telephony-carrier"; 4882 4883 case URL_PREFERAPN_USING_SUBID: 4884 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: 4885 case URL_PREFERAPN: 4886 case URL_PREFERAPN_NO_UPDATE: 4887 case URL_PREFERAPNSET: 4888 case URL_PREFERAPNSET_USING_SUBID: 4889 return "vnd.android.cursor.item/telephony-carrier"; 4890 4891 default: 4892 throw new IllegalArgumentException("Unknown URL " + url); 4893 } 4894 } 4895 4896 /** 4897 * Insert an array of ContentValues and call notifyChange at the end. 4898 */ 4899 @Override bulkInsert(Uri url, ContentValues[] values)4900 public int bulkInsert(Uri url, ContentValues[] values) { 4901 mDefaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 4902 synchronized (this) { 4903 return unsynchronizedBulkInsert(url, values); 4904 } 4905 } 4906 4907 /** 4908 * Do a bulk insert while inside a synchronized function. This is typically not safe and should 4909 * only be done when you are sure there will be no conflict. 4910 */ unsynchronizedBulkInsert(Uri url, ContentValues[] values)4911 private int unsynchronizedBulkInsert(Uri url, ContentValues[] values) { 4912 int count = 0; 4913 boolean notify = false; 4914 for (ContentValues value : values) { 4915 Pair<Uri, Boolean> rowAndNotify = insertSingleRow(url, value); 4916 if (rowAndNotify.first != null) { 4917 count++; 4918 } 4919 if (rowAndNotify.second == true) { 4920 notify = true; 4921 } 4922 } 4923 if (notify) { 4924 getContext().getContentResolver().notifyChange(CONTENT_URI, null, 4925 true, UserHandle.USER_ALL); 4926 } 4927 return count; 4928 } 4929 4930 @Override insert(Uri url, ContentValues initialValues)4931 public Uri insert(Uri url, ContentValues initialValues) { 4932 mDefaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 4933 return insertSynchronized(url, initialValues); 4934 } 4935 insertSynchronized(Uri url, ContentValues initialValues)4936 private synchronized Uri insertSynchronized(Uri url, ContentValues initialValues) { 4937 Pair<Uri, Boolean> rowAndNotify = insertSingleRow(url, initialValues); 4938 if (rowAndNotify.second) { 4939 getContext().getContentResolver().notifyChange(CONTENT_URI, null, 4940 true, UserHandle.USER_ALL); 4941 } 4942 return rowAndNotify.first; 4943 } 4944 4945 /** 4946 * Internal insert function to prevent code duplication for URL_TELEPHONY and URL_DPC. 4947 * 4948 * @param values the value that caller wants to insert 4949 * @return a pair in which the first element refers to the Uri for the row inserted, the second 4950 * element refers to whether sends out notification. 4951 */ insertRowWithValue(ContentValues values)4952 private Pair<Uri, Boolean> insertRowWithValue(ContentValues values) { 4953 Uri result = null; 4954 boolean notify = false; 4955 SQLiteDatabase db = getWritableDatabase(); 4956 4957 try { 4958 // Abort on conflict of unique fields and attempt merge 4959 long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values, 4960 SQLiteDatabase.CONFLICT_ABORT); 4961 if (rowID >= 0) { 4962 result = ContentUris.withAppendedId(CONTENT_URI, rowID); 4963 notify = true; 4964 } 4965 if (DBG) log("insert: inserted " + values + ", rowID = " + rowID); 4966 } catch (SQLException e) { 4967 log("insert: exception " + e); 4968 // Insertion failed which could be due to a conflict. Check if that is the case 4969 // and merge the entries 4970 Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values); 4971 if (oldRow != null) { 4972 ContentValues mergedValues = new ContentValues(); 4973 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values, 4974 mergedValues, false, getContext()); 4975 oldRow.close(); 4976 notify = true; 4977 } 4978 } 4979 return Pair.create(result, notify); 4980 } 4981 insertSingleRow(Uri url, ContentValues initialValues)4982 private Pair<Uri, Boolean> insertSingleRow(Uri url, ContentValues initialValues) { 4983 Uri result = null; 4984 int subId = mDefaultSubId; 4985 4986 int match = s_urlMatcher.match(url); 4987 checkPermission(match); 4988 syncBearerBitmaskAndNetworkTypeBitmask(initialValues); 4989 4990 boolean notify = false; 4991 SQLiteDatabase db = getWritableDatabase(); 4992 switch (match) 4993 { 4994 case URL_TELEPHONY_USING_SUBID: 4995 { 4996 loge("insert carriers/subId/* is not supported, treat as carriers"); 4997 } 4998 //intentional fall through from above case 4999 5000 case URL_TELEPHONY: 5001 { 5002 ContentValues values; 5003 if (initialValues != null) { 5004 values = new ContentValues(initialValues); 5005 } else { 5006 values = new ContentValues(); 5007 } 5008 5009 values = setDefaultValue(values); 5010 if (!values.containsKey(EDITED_STATUS)) { 5011 values.put(EDITED_STATUS, CARRIER_EDITED); 5012 } 5013 // Owned_by should be others if inserted via general uri. 5014 values.put(OWNED_BY, OWNED_BY_OTHERS); 5015 5016 Pair<Uri, Boolean> ret = insertRowWithValue(values); 5017 result = ret.first; 5018 notify = ret.second; 5019 break; 5020 } 5021 5022 case URL_CURRENT_USING_SUBID: 5023 { 5024 loge("insert carriers/current/subId/* is not supported, treat as carriers/current"); 5025 } 5026 //intentional fall through from above case 5027 5028 case URL_CURRENT: 5029 { 5030 // zero out the previous operator 5031 db.update(CARRIERS_TABLE, s_currentNullMap, CURRENT + "!=0", null); 5032 5033 String numeric = initialValues.getAsString(NUMERIC); 5034 int updated = db.update(CARRIERS_TABLE, s_currentSetMap, 5035 NUMERIC + " = '" + numeric + "'", null); 5036 5037 if (updated > 0) 5038 { 5039 if (VDBG) log("Setting numeric '" + numeric + "' to be the current operator"); 5040 } 5041 else 5042 { 5043 loge("Failed setting numeric '" + numeric + "' to the current operator"); 5044 } 5045 break; 5046 } 5047 5048 case URL_PREFERAPN_USING_SUBID: 5049 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: 5050 { 5051 String subIdString = url.getLastPathSegment(); 5052 try { 5053 subId = Integer.parseInt(subIdString); 5054 } catch (NumberFormatException e) { 5055 loge("NumberFormatException" + e); 5056 return Pair.create(result, notify); 5057 } 5058 } 5059 //intentional fall through from above case 5060 5061 case URL_PREFERAPN: 5062 case URL_PREFERAPN_NO_UPDATE: 5063 { 5064 if (initialValues != null) { 5065 if(initialValues.containsKey(COLUMN_APN_ID)) { 5066 setPreferredApnId(initialValues.getAsLong(COLUMN_APN_ID), subId, true); 5067 notify = true; 5068 } 5069 } 5070 break; 5071 } 5072 5073 case URL_DPC: { 5074 ensureCallingFromSystemOrPhoneUid("URL_DPC called from non SYSTEM_UID."); 5075 5076 ContentValues values; 5077 if (initialValues != null) { 5078 values = new ContentValues(initialValues); 5079 } else { 5080 values = new ContentValues(); 5081 } 5082 5083 // Owned_by should be DPC if inserted via URL_DPC. 5084 values.put(OWNED_BY, OWNED_BY_DPC); 5085 // DPC records should not be user editable. 5086 values.put(USER_EDITABLE, false); 5087 5088 final long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values, 5089 SQLiteDatabase.CONFLICT_IGNORE); 5090 if (rowID >= 0) { 5091 result = ContentUris.withAppendedId(CONTENT_URI, rowID); 5092 notify = true; 5093 } 5094 if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID); 5095 5096 break; 5097 } 5098 5099 case URL_SIMINFO: { 5100 long id = db.insert(SIMINFO_TABLE, null, initialValues); 5101 result = ContentUris.withAppendedId(Telephony.SimInfo.CONTENT_URI, id); 5102 break; 5103 } 5104 } 5105 5106 return Pair.create(result, notify); 5107 } 5108 5109 @Override delete(Uri url, String where, String[] whereArgs)5110 public int delete(Uri url, String where, String[] whereArgs) { 5111 mDefaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 5112 return deleteSynchronized(url, where, whereArgs); 5113 } 5114 deleteSynchronized(Uri url, String where, String[] whereArgs)5115 private synchronized int deleteSynchronized(Uri url, String where, String[] whereArgs) { 5116 int count = 0; 5117 int subId = mDefaultSubId; 5118 String userOrCarrierEdited = ") and (" + 5119 IS_USER_EDITED + " or " + 5120 IS_CARRIER_EDITED + ")"; 5121 String notUserOrCarrierEdited = ") and (" + 5122 IS_NOT_USER_EDITED + " and " + 5123 IS_NOT_CARRIER_EDITED + ")"; 5124 String unedited = ") and " + IS_UNEDITED; 5125 ContentValues cv = new ContentValues(); 5126 cv.put(EDITED_STATUS, USER_DELETED); 5127 5128 int match = s_urlMatcher.match(url); 5129 checkPermission(match); 5130 5131 SQLiteDatabase db = getWritableDatabase(); 5132 switch (match) 5133 { 5134 case URL_DELETE: 5135 { 5136 // Delete preferred APN for all subIds 5137 deletePreferredApnId(getContext()); 5138 // Delete unedited entries 5139 count = db.delete(CARRIERS_TABLE, "(" + where + unedited + " and " + 5140 IS_NOT_OWNED_BY_DPC, whereArgs); 5141 break; 5142 } 5143 5144 case URL_TELEPHONY_USING_SUBID: 5145 { 5146 loge("delete carriers/subId/* is not supported, treat as carriers"); 5147 } 5148 //intentional fall through from above case 5149 5150 case URL_TELEPHONY: 5151 { 5152 // Delete user/carrier edited entries 5153 count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited 5154 + " and " + IS_NOT_OWNED_BY_DPC, whereArgs); 5155 // Otherwise mark as user deleted instead of deleting 5156 count += db.update(CARRIERS_TABLE, cv, "(" + where + 5157 notUserOrCarrierEdited + " and " + IS_NOT_OWNED_BY_DPC, whereArgs); 5158 break; 5159 } 5160 5161 case URL_CURRENT_USING_SUBID: { 5162 loge("delete carriers/current/subId/* is not supported, treat as carriers/current"); 5163 } 5164 //intentional fall through from above case 5165 5166 case URL_CURRENT: 5167 { 5168 // Delete user/carrier edited entries 5169 count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited 5170 + " and " + IS_NOT_OWNED_BY_DPC, whereArgs); 5171 // Otherwise mark as user deleted instead of deleting 5172 count += db.update(CARRIERS_TABLE, cv, "(" + where + 5173 notUserOrCarrierEdited + " and " + IS_NOT_OWNED_BY_DPC, whereArgs); 5174 break; 5175 } 5176 5177 case URL_ID: 5178 { 5179 // Delete user/carrier edited entries 5180 count = db.delete(CARRIERS_TABLE, 5181 "(" + _ID + "=?" + userOrCarrierEdited + 5182 " and " + IS_NOT_OWNED_BY_DPC, 5183 new String[] { url.getLastPathSegment() }); 5184 // Otherwise mark as user deleted instead of deleting 5185 count += db.update(CARRIERS_TABLE, cv, 5186 "(" + _ID + "=?" + notUserOrCarrierEdited + 5187 " and " + IS_NOT_OWNED_BY_DPC, 5188 new String[]{url.getLastPathSegment() }); 5189 break; 5190 } 5191 5192 case URL_RESTOREAPN_USING_SUBID: { 5193 String subIdString = url.getLastPathSegment(); 5194 try { 5195 subId = Integer.parseInt(subIdString); 5196 } catch (NumberFormatException e) { 5197 loge("NumberFormatException" + e); 5198 throw new IllegalArgumentException("Invalid subId " + url); 5199 } 5200 } 5201 // intentional fall through from above case 5202 5203 case URL_RESTOREAPN: { 5204 count = 1; 5205 restoreDefaultAPN(subId); 5206 getContext().getContentResolver().notifyChange( 5207 Uri.withAppendedPath(CONTENT_URI, "restore/subId/" + subId), null, 5208 true, UserHandle.USER_ALL); 5209 break; 5210 } 5211 5212 case URL_PREFERAPN_USING_SUBID: 5213 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: { 5214 String subIdString = url.getLastPathSegment(); 5215 try { 5216 subId = Integer.parseInt(subIdString); 5217 } catch (NumberFormatException e) { 5218 loge("NumberFormatException" + e); 5219 throw new IllegalArgumentException("Invalid subId " + url); 5220 } 5221 } 5222 //intentional fall through from above case 5223 5224 case URL_PREFERAPN: 5225 case URL_PREFERAPN_NO_UPDATE: 5226 { 5227 setPreferredApnId((long)INVALID_APN_ID, subId, true); 5228 if ((match == URL_PREFERAPN) || (match == URL_PREFERAPN_USING_SUBID)) count = 1; 5229 break; 5230 } 5231 5232 case URL_DPC_ID: { 5233 ensureCallingFromSystemOrPhoneUid("URL_DPC_ID called from non SYSTEM_UID."); 5234 5235 // Only delete if owned by DPC. 5236 count = db.delete(CARRIERS_TABLE, "(" + _ID + "=?)" + " and " + IS_OWNED_BY_DPC, 5237 new String[] { url.getLastPathSegment() }); 5238 break; 5239 } 5240 5241 case URL_SIMINFO: { 5242 count = db.delete(SIMINFO_TABLE, where, whereArgs); 5243 break; 5244 } 5245 5246 case URL_UPDATE_DB: { 5247 updateApnDb(); 5248 count = 1; 5249 break; 5250 } 5251 5252 default: { 5253 throw new UnsupportedOperationException("Cannot delete that URL: " + url); 5254 } 5255 } 5256 5257 if (count > 0) { 5258 getContext().getContentResolver().notifyChange(CONTENT_URI, null, 5259 true, UserHandle.USER_ALL); 5260 } 5261 5262 return count; 5263 } 5264 5265 @Override update(Uri url, ContentValues values, String where, String[] whereArgs)5266 public int update(Uri url, ContentValues values, String where, String[] whereArgs) 5267 { 5268 mDefaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 5269 return updateSynchronized(url, values, where, whereArgs); 5270 } 5271 updateSynchronized(Uri url, ContentValues values, String where, String[] whereArgs)5272 private synchronized int updateSynchronized(Uri url, ContentValues values, String where, 5273 String[] whereArgs) { 5274 int count = 0; 5275 int uriType = URL_UNKNOWN; 5276 int subId = mDefaultSubId; 5277 5278 int match = s_urlMatcher.match(url); 5279 checkPermission(match); 5280 syncBearerBitmaskAndNetworkTypeBitmask(values); 5281 5282 SQLiteDatabase db = getWritableDatabase(); 5283 switch (match) 5284 { 5285 case URL_TELEPHONY_USING_SUBID: 5286 { 5287 loge("insert carriers/subId/* is not supported, treat as carriers"); 5288 } 5289 //intentional fall through from above case 5290 5291 case URL_TELEPHONY: 5292 { 5293 if (!values.containsKey(EDITED_STATUS)) { 5294 values.put(EDITED_STATUS, CARRIER_EDITED); 5295 } 5296 5297 // Replace on conflict so that if same APN is present in db with edited 5298 // as UNEDITED or USER/CARRIER_DELETED, it is replaced with 5299 // edited USER/CARRIER_EDITED 5300 count = db.updateWithOnConflict(CARRIERS_TABLE, values, where + 5301 " and " + IS_NOT_OWNED_BY_DPC, whereArgs, 5302 SQLiteDatabase.CONFLICT_REPLACE); 5303 break; 5304 } 5305 5306 case URL_CURRENT_USING_SUBID: 5307 { 5308 loge("insert carriers/current/subId/* is not supported, treat as carriers/current"); 5309 } 5310 //intentional fall through from above case 5311 5312 case URL_CURRENT: 5313 { 5314 if (!values.containsKey(EDITED_STATUS)) { 5315 values.put(EDITED_STATUS, CARRIER_EDITED); 5316 } 5317 // Replace on conflict so that if same APN is present in db with edited 5318 // as UNEDITED or USER/CARRIER_DELETED, it is replaced with 5319 // edited USER/CARRIER_EDITED 5320 count = db.updateWithOnConflict(CARRIERS_TABLE, values, where + 5321 " and " + IS_NOT_OWNED_BY_DPC, 5322 whereArgs, SQLiteDatabase.CONFLICT_REPLACE); 5323 break; 5324 } 5325 5326 case URL_ID: 5327 { 5328 String rowID = url.getLastPathSegment(); 5329 if (where != null || whereArgs != null) { 5330 throw new UnsupportedOperationException( 5331 "Cannot update URL " + url + " with a where clause"); 5332 } 5333 if (!values.containsKey(EDITED_STATUS)) { 5334 values.put(EDITED_STATUS, CARRIER_EDITED); 5335 } 5336 5337 try { 5338 count = db.updateWithOnConflict(CARRIERS_TABLE, values, _ID + "=?" + " and " + 5339 IS_NOT_OWNED_BY_DPC, new String[] { rowID }, 5340 SQLiteDatabase.CONFLICT_ABORT); 5341 } catch (SQLException e) { 5342 // Update failed which could be due to a conflict. Check if that is 5343 // the case and merge the entries 5344 log("update: exception " + e); 5345 Cursor oldRow = selectConflictingRow(db, CARRIERS_TABLE, values); 5346 if (oldRow != null) { 5347 ContentValues mergedValues = new ContentValues(); 5348 mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values, 5349 mergedValues, false, getContext()); 5350 oldRow.close(); 5351 db.delete(CARRIERS_TABLE, _ID + "=?" + " and " + IS_NOT_OWNED_BY_DPC, 5352 new String[] { rowID }); 5353 } 5354 } 5355 break; 5356 } 5357 5358 case URL_PREFERAPN_USING_SUBID: 5359 case URL_PREFERAPN_NO_UPDATE_USING_SUBID: 5360 { 5361 String subIdString = url.getLastPathSegment(); 5362 try { 5363 subId = Integer.parseInt(subIdString); 5364 } catch (NumberFormatException e) { 5365 loge("NumberFormatException" + e); 5366 throw new IllegalArgumentException("Invalid subId " + url); 5367 } 5368 } 5369 5370 case URL_PREFERAPN: 5371 case URL_PREFERAPN_NO_UPDATE: 5372 { 5373 if (values != null) { 5374 if (values.containsKey(COLUMN_APN_ID)) { 5375 setPreferredApnId(values.getAsLong(COLUMN_APN_ID), subId, true); 5376 if ((match == URL_PREFERAPN) || 5377 (match == URL_PREFERAPN_USING_SUBID)) { 5378 count = 1; 5379 } 5380 } 5381 } 5382 break; 5383 } 5384 5385 case URL_DPC_ID: 5386 { 5387 ensureCallingFromSystemOrPhoneUid("URL_DPC_ID called from non SYSTEM_UID."); 5388 5389 if (where != null || whereArgs != null) { 5390 throw new UnsupportedOperationException( 5391 "Cannot update URL " + url + " with a where clause"); 5392 } 5393 count = db.updateWithOnConflict(CARRIERS_TABLE, values, 5394 _ID + "=?" + " and " + IS_OWNED_BY_DPC, 5395 new String[] { url.getLastPathSegment() }, SQLiteDatabase.CONFLICT_IGNORE); 5396 break; 5397 } 5398 5399 case URL_ENFORCE_MANAGED: { 5400 ensureCallingFromSystemOrPhoneUid( 5401 "URL_ENFORCE_MANAGED called from non SYSTEM_UID."); 5402 if (values != null) { 5403 if (values.containsKey(ENFORCED_KEY)) { 5404 setManagedApnEnforced(values.getAsBoolean(ENFORCED_KEY)); 5405 count = 1; 5406 } 5407 } 5408 break; 5409 } 5410 5411 case URL_SIMINFO_USING_SUBID: 5412 String subIdString = url.getLastPathSegment(); 5413 try { 5414 subId = Integer.parseInt(subIdString); 5415 } catch (NumberFormatException e) { 5416 loge("NumberFormatException" + e); 5417 throw new IllegalArgumentException("Invalid subId " + url); 5418 } 5419 if (where != null || whereArgs != null) { 5420 throw new UnsupportedOperationException( 5421 "Cannot update URL " + url + " with a where clause"); 5422 } 5423 count = db.update(SIMINFO_TABLE, values, _ID + "=?", 5424 new String[] { subIdString}); 5425 uriType = URL_SIMINFO_USING_SUBID; 5426 break; 5427 5428 case URL_SIMINFO: { 5429 count = db.update(SIMINFO_TABLE, values, where, whereArgs); 5430 uriType = URL_SIMINFO; 5431 break; 5432 } 5433 5434 case URL_SIMINFO_SUW_RESTORE: 5435 count = db.update(SIMINFO_TABLE, values, where, whereArgs); 5436 uriType = URL_SIMINFO_SUW_RESTORE; 5437 break; 5438 5439 case URL_SIMINFO_SIM_INSERTED_RESTORE: 5440 count = db.update(SIMINFO_TABLE, values, where, whereArgs); 5441 break; 5442 5443 default: { 5444 throw new UnsupportedOperationException("Cannot update that URL: " + url); 5445 } 5446 } 5447 5448 // if APNs (CARRIERS_TABLE) have been updated, some of them may be preferred APN for 5449 // different subs. So update the APN field values saved in SharedPref for all subIds. 5450 switch (match) { 5451 case URL_TELEPHONY_USING_SUBID: 5452 case URL_TELEPHONY: 5453 case URL_CURRENT_USING_SUBID: 5454 case URL_CURRENT: 5455 case URL_ID: 5456 case URL_DPC_ID: 5457 updatePreferredApns(); 5458 break; 5459 } 5460 5461 if (count > 0) { 5462 boolean usingSubId = false; 5463 switch (uriType) { 5464 case URL_SIMINFO_SIM_INSERTED_RESTORE: 5465 break; 5466 case URL_SIMINFO_SUW_RESTORE: 5467 getContext().getContentResolver().notifyChange( 5468 SubscriptionManager.SIM_INFO_SUW_RESTORE_CONTENT_URI, null); 5469 // intentional fall through from above case 5470 case URL_SIMINFO_USING_SUBID: 5471 usingSubId = true; 5472 // intentional fall through from above case 5473 case URL_SIMINFO: 5474 // skip notifying descendant URLs to avoid unneccessary wake up. 5475 // If not set, any change to SIMINFO will notify observers which listens to 5476 // specific field of SIMINFO. 5477 getContext().getContentResolver().notifyChange( 5478 Telephony.SimInfo.CONTENT_URI, null, 5479 ContentResolver.NOTIFY_SYNC_TO_NETWORK 5480 | ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS, 5481 UserHandle.USER_ALL); 5482 // notify observers on specific user settings changes. 5483 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ENABLED)) { 5484 getContext().getContentResolver().notifyChange( 5485 getNotifyContentUri(SubscriptionManager.WFC_ENABLED_CONTENT_URI, 5486 usingSubId, subId), null, true, UserHandle.USER_ALL); 5487 } 5488 if (values.containsKey(Telephony.SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED)) { 5489 getContext().getContentResolver().notifyChange( 5490 getNotifyContentUri(SubscriptionManager 5491 .ADVANCED_CALLING_ENABLED_CONTENT_URI, 5492 usingSubId, subId), null, true, UserHandle.USER_ALL); 5493 } 5494 if (values.containsKey(Telephony.SimInfo.COLUMN_VT_IMS_ENABLED)) { 5495 getContext().getContentResolver().notifyChange( 5496 getNotifyContentUri(SubscriptionManager.VT_ENABLED_CONTENT_URI, 5497 usingSubId, subId), null, true, UserHandle.USER_ALL); 5498 } 5499 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_MODE)) { 5500 getContext().getContentResolver().notifyChange( 5501 getNotifyContentUri(SubscriptionManager.WFC_MODE_CONTENT_URI, 5502 usingSubId, subId), null, true, UserHandle.USER_ALL); 5503 } 5504 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_MODE)) { 5505 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5506 SubscriptionManager.WFC_ROAMING_MODE_CONTENT_URI, 5507 usingSubId, subId), null, true, UserHandle.USER_ALL); 5508 } 5509 if (values.containsKey(Telephony.SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED)) { 5510 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5511 SubscriptionManager.WFC_ROAMING_ENABLED_CONTENT_URI, 5512 usingSubId, subId), null, true, UserHandle.USER_ALL); 5513 } 5514 if (values.containsKey(Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED)) { 5515 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5516 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5517 Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED), 5518 usingSubId, subId), null, true, UserHandle.USER_ALL); 5519 } 5520 if (values.containsKey(Telephony.SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED)) { 5521 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5522 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5523 Telephony.SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED), 5524 usingSubId, subId), null, true, UserHandle.USER_ALL); 5525 } 5526 if (values.containsKey(Telephony.SimInfo.COLUMN_VOIMS_OPT_IN_STATUS)) { 5527 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5528 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5529 Telephony.SimInfo.COLUMN_VOIMS_OPT_IN_STATUS), 5530 usingSubId, subId), null, true, UserHandle.USER_ALL); 5531 } 5532 if (values.containsKey(Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED)) { 5533 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5534 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5535 Telephony.SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED), 5536 usingSubId, subId), null, true, UserHandle.USER_ALL); 5537 } 5538 if (values.containsKey(Telephony.SimInfo.COLUMN_USAGE_SETTING)) { 5539 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5540 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5541 Telephony.SimInfo.COLUMN_USAGE_SETTING), 5542 usingSubId, subId), null, true, UserHandle.USER_ALL); 5543 } 5544 if (values.containsKey(Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES)) { 5545 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5546 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5547 Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES), 5548 usingSubId, subId), null, true, UserHandle.USER_ALL); 5549 } 5550 if (values.containsKey( 5551 Telephony.SimInfo.COLUMN_SERVICE_CAPABILITIES)) { 5552 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5553 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5554 Telephony.SimInfo.COLUMN_SERVICE_CAPABILITIES), 5555 usingSubId, subId), null, true, UserHandle.USER_ALL); 5556 } 5557 if (values.containsKey( 5558 Telephony.SimInfo.COLUMN_TRANSFER_STATUS)) { 5559 getContext().getContentResolver().notifyChange(getNotifyContentUri( 5560 Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI, 5561 Telephony.SimInfo.COLUMN_TRANSFER_STATUS), 5562 usingSubId, subId), null, true, UserHandle.USER_ALL); 5563 } 5564 break; 5565 default: 5566 getContext().getContentResolver().notifyChange( 5567 CONTENT_URI, null, true, UserHandle.USER_ALL); 5568 } 5569 } 5570 5571 return count; 5572 } 5573 getNotifyContentUri(Uri uri, boolean usingSubId, int subId)5574 private static Uri getNotifyContentUri(Uri uri, boolean usingSubId, int subId) { 5575 return (usingSubId) ? Uri.withAppendedPath(uri, "" + subId) : uri; 5576 } 5577 5578 /** 5579 * Checks permission to query or insert/update/delete the database. The permissions required 5580 * for APN DB and SIMINFO DB are different: 5581 * <ul> 5582 * <li>APN DB requires WRITE_APN_SETTINGS or carrier privileges 5583 * <li>SIMINFO DB requires phone UID; it's for phone internal usage only 5584 * </ul> 5585 */ checkPermission(int match)5586 private void checkPermission(int match) { 5587 switch (match) { 5588 case URL_SIMINFO: 5589 case URL_SIMINFO_USING_SUBID: 5590 case URL_SIMINFO_SUW_RESTORE: 5591 case URL_SIMINFO_SIM_INSERTED_RESTORE: 5592 checkPermissionForSimInfoTable(); 5593 break; 5594 default: 5595 checkPermissionForApnTable(); 5596 } 5597 } 5598 checkPermissionForApnTable()5599 private void checkPermissionForApnTable() { 5600 int status = getContext().checkCallingOrSelfPermission( 5601 "android.permission.WRITE_APN_SETTINGS"); 5602 if (status == PackageManager.PERMISSION_GRANTED) { 5603 return; 5604 } 5605 5606 PackageManager packageManager = getContext().getPackageManager(); 5607 if (Flags.hsumPackageManager()) { 5608 packageManager = getContext().createContextAsUser(Binder.getCallingUserHandle(), 0) 5609 .getPackageManager(); 5610 } 5611 String[] packages = packageManager.getPackagesForUid(Binder.getCallingUid()); 5612 5613 TelephonyManager telephonyManager = 5614 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); 5615 final long token = Binder.clearCallingIdentity(); 5616 try { 5617 for (String pkg : packages) { 5618 if (telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(pkg) == 5619 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 5620 return; 5621 } 5622 } 5623 } finally { 5624 Binder.restoreCallingIdentity(token); 5625 } 5626 5627 throw new SecurityException("No permission to access APN settings"); 5628 } 5629 5630 /** 5631 * Check permission to query the database based on PlatformCompat settings -- if the compat 5632 * change is enabled, check WRITE_APN_SETTINGS or carrier privs for all queries. Otherwise, 5633 * use the legacy checkQueryPermission method to see if the query should be allowed. 5634 */ checkPermissionCompat(int match, String[] projectionIn)5635 private void checkPermissionCompat(int match, String[] projectionIn) { 5636 boolean useNewBehavior = CompatChanges.isChangeEnabled( 5637 Telephony.Carriers.APN_READING_PERMISSION_CHANGE_ID, 5638 Binder.getCallingUid()); 5639 5640 if (!useNewBehavior) { 5641 log("Using old permission behavior for telephony provider compat"); 5642 checkQueryPermission(match, projectionIn); 5643 } else { 5644 checkPermission(match); 5645 } 5646 } 5647 checkQueryPermission(int match, String[] projectionIn)5648 private void checkQueryPermission(int match, String[] projectionIn) { 5649 if (match == URL_SIMINFO) { 5650 checkPermissionForSimInfoTable(); 5651 } else { 5652 if (projectionIn != null) { 5653 for (String column : projectionIn) { 5654 if (TYPE.equals(column) || 5655 MMSC.equals(column) || 5656 MMSPROXY.equals(column) || 5657 MMSPORT.equals(column) || 5658 MVNO_TYPE.equals(column) || 5659 MVNO_MATCH_DATA.equals(column) || 5660 APN.equals(column)) { 5661 // noop 5662 } else { 5663 checkPermissionForApnTable(); 5664 break; 5665 } 5666 } 5667 } else { 5668 // null returns all columns, so need permission check 5669 checkPermissionForApnTable(); 5670 } 5671 } 5672 } 5673 checkPermissionForSimInfoTable()5674 private void checkPermissionForSimInfoTable() { 5675 ensureCallingFromSystemOrPhoneUid("Access SIMINFO table from not phone/system UID"); 5676 if (getContext().checkCallingOrSelfPermission( 5677 "android.permission.ACCESS_TELEPHONY_SIMINFO_DB") 5678 == PackageManager.PERMISSION_GRANTED) { 5679 return; 5680 } 5681 throw new SecurityException("No permission to access SIMINFO table"); 5682 } 5683 5684 private DatabaseHelper mOpenHelper; 5685 restoreDefaultAPN(int subId)5686 private void restoreDefaultAPN(int subId) { 5687 SQLiteDatabase db = getWritableDatabase(); 5688 TelephonyManager telephonyManager = 5689 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); 5690 String where = null; 5691 if (telephonyManager.getPhoneCount() > 1) { 5692 where = getWhereClauseForRestoreDefaultApn(db, subId); 5693 } 5694 if (TextUtils.isEmpty(where)) { 5695 where = IS_NOT_OWNED_BY_DPC; 5696 } 5697 log("restoreDefaultAPN: where: " + where); 5698 5699 try { 5700 db.delete(CARRIERS_TABLE, where, null); 5701 } catch (SQLException e) { 5702 loge("got exception when deleting to restore: " + e); 5703 } 5704 5705 // delete preferred apn ids and preferred apns (both stored in diff SharedPref) for all 5706 // subIds 5707 SharedPreferences spApnId = getContext().getSharedPreferences(PREF_FILE_APN, 5708 Context.MODE_PRIVATE); 5709 SharedPreferences.Editor editorApnId = spApnId.edit(); 5710 editorApnId.clear(); 5711 editorApnId.apply(); 5712 5713 SharedPreferences spApn = getContext().getSharedPreferences(PREF_FILE_FULL_APN, 5714 Context.MODE_PRIVATE); 5715 SharedPreferences.Editor editorApn = spApn.edit(); 5716 editorApn.clear(); 5717 editorApn.apply(); 5718 5719 if (apnSourceServiceExists(getContext())) { 5720 restoreApnsWithService(subId); 5721 } else { 5722 initDatabaseWithDatabaseHelper(db); 5723 } 5724 } 5725 getWhereClauseForRestoreDefaultApn(SQLiteDatabase db, int subId)5726 private String getWhereClauseForRestoreDefaultApn(SQLiteDatabase db, int subId) { 5727 TelephonyManager telephonyManager = 5728 getContext().getSystemService(TelephonyManager.class).createForSubscriptionId(subId); 5729 String simOperator = telephonyManager.getSimOperator(); 5730 int simCarrierId = telephonyManager.getSimSpecificCarrierId(); 5731 Cursor cursor = db.query(CARRIERS_TABLE, new String[] {MVNO_TYPE, MVNO_MATCH_DATA}, 5732 NUMERIC + "='" + simOperator + "'", null, null, null, DEFAULT_SORT_ORDER); 5733 String where = null; 5734 5735 if (cursor != null) { 5736 cursor.moveToFirst(); 5737 while (!cursor.isAfterLast()) { 5738 String mvnoType = cursor.getString(0 /* MVNO_TYPE index */); 5739 String mvnoMatchData = cursor.getString(1 /* MVNO_MATCH_DATA index */); 5740 if (!TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData) 5741 && telephonyManager.matchesCurrentSimOperator(simOperator, 5742 getMvnoTypeIntFromString(mvnoType), mvnoMatchData)) { 5743 where = NUMERIC + "='" + simOperator + "'" 5744 + " AND " + MVNO_TYPE + "='" + mvnoType + "'" 5745 + " AND " + MVNO_MATCH_DATA + "='" + mvnoMatchData + "'" 5746 + " AND " + IS_NOT_OWNED_BY_DPC; 5747 break; 5748 } 5749 cursor.moveToNext(); 5750 } 5751 cursor.close(); 5752 5753 if (TextUtils.isEmpty(where)) { 5754 where = NUMERIC + "='" + simOperator + "'" 5755 + " AND (" + MVNO_TYPE + "='' OR " + MVNO_MATCH_DATA + "='')" 5756 + " AND " + IS_NOT_OWNED_BY_DPC; 5757 } 5758 // Add carrier id APNs 5759 if (TelephonyManager.UNKNOWN_CARRIER_ID < simCarrierId) { 5760 where = where.concat(" OR " + CARRIER_ID + " = '" + simCarrierId + "'" + " AND " 5761 + IS_NOT_OWNED_BY_DPC); 5762 } 5763 5764 } 5765 return where; 5766 } 5767 updateApnDb()5768 private synchronized void updateApnDb() { 5769 if (apnSourceServiceExists(getContext())) { 5770 loge("called updateApnDb when apn source service exists"); 5771 return; 5772 } 5773 5774 // On first boot getWritableDatabase() triggers 5775 // DatabaseHelper.onCreate() which in turn will call initDatabase. 5776 // To avoid loading APNs twice call getWritableDatabase() before needApnDbUpdate() 5777 SQLiteDatabase db = getWritableDatabase(); 5778 5779 if (!needApnDbUpdate()) { 5780 log("Skipping apn db update since apn-conf has not changed."); 5781 return; 5782 } 5783 5784 // Delete preferred APN for all subIds 5785 deletePreferredApnId(getContext()); 5786 5787 // Delete entries in db 5788 try { 5789 if (VDBG) log("updateApnDb: deleting edited=UNEDITED entries"); 5790 db.delete(CARRIERS_TABLE, IS_UNEDITED + " and " + IS_NOT_OWNED_BY_DPC, null); 5791 } catch (SQLException e) { 5792 loge("got exception when deleting to update: " + e); 5793 } 5794 5795 initDatabaseWithDatabaseHelper(db); 5796 5797 // Notify listeners of DB change since DB has been updated 5798 getContext().getContentResolver().notifyChange( 5799 CONTENT_URI, null, true, UserHandle.USER_ALL); 5800 5801 } 5802 fillInMccMncStringAtCursor(Context context, SQLiteDatabase db, Cursor c)5803 public static void fillInMccMncStringAtCursor(Context context, SQLiteDatabase db, Cursor c) { 5804 int mcc, mnc; 5805 String subId; 5806 try { 5807 mcc = c.getInt(c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_MCC)); 5808 mnc = c.getInt(c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_MNC)); 5809 subId = c.getString(c.getColumnIndexOrThrow( 5810 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID)); 5811 } catch (IllegalArgumentException e) { 5812 Log.e(TAG, "Possible database corruption -- some columns not found."); 5813 return; 5814 } 5815 5816 String mccString = String.format(Locale.getDefault(), "%03d", mcc); 5817 String mncString = getBestStringMnc(context, mccString, mnc); 5818 ContentValues cv = new ContentValues(2); 5819 cv.put(Telephony.SimInfo.COLUMN_MCC_STRING, mccString); 5820 cv.put(Telephony.SimInfo.COLUMN_MNC_STRING, mncString); 5821 db.update(SIMINFO_TABLE, cv, 5822 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?", 5823 new String[]{subId}); 5824 } 5825 5826 /* 5827 * Find the best string-form mnc by looking up possibilities in the carrier id db. 5828 * Default to the three-digit version if neither/both are valid. 5829 */ getBestStringMnc(Context context, String mcc, int mnc)5830 private static String getBestStringMnc(Context context, String mcc, int mnc) { 5831 if (mnc >= 100 && mnc <= 999) { 5832 return String.valueOf(mnc); 5833 } 5834 String twoDigitMnc = String.format(Locale.getDefault(), "%02d", mnc); 5835 String threeDigitMnc = "0" + twoDigitMnc; 5836 boolean threeDigitNetworkCode = 5837 Arrays.asList(COUNTRY_MCC_WITH_THREE_DIGIT_MNC).contains(mcc); 5838 int twoDigitResult = countMccMncInCarrierList(context, mcc + twoDigitMnc); 5839 int threeDigitResult = countMccMncInCarrierList(context, mcc + threeDigitMnc); 5840 5841 if ((threeDigitResult > twoDigitResult) || 5842 (threeDigitNetworkCode && (twoDigitResult == threeDigitResult))) { 5843 return threeDigitMnc; 5844 } else { 5845 return twoDigitMnc; 5846 } 5847 } 5848 5849 /** 5850 * Check carrier_list how many mcc mnc combo matches there are 5851 */ countMccMncInCarrierList(Context ctx, String mccMncCombo)5852 private static int countMccMncInCarrierList(Context ctx, String mccMncCombo) { 5853 try ( 5854 Cursor mccMncCursor = ctx.getContentResolver().query( 5855 Telephony.CarrierId.All.CONTENT_URI, 5856 /* projection */ null, 5857 /* selection */ Telephony.CarrierId.All.MCCMNC + "=?", 5858 /* selectionArgs */ new String[]{mccMncCombo}, null); 5859 ) 5860 { 5861 return mccMncCursor.getCount(); 5862 } 5863 } 5864 5865 /** 5866 * Sync the bearer bitmask and network type bitmask when inserting and updating. 5867 * Since bearerBitmask is deprecating, map the networkTypeBitmask to bearerBitmask if 5868 * networkTypeBitmask was provided. But if networkTypeBitmask was not provided, map the 5869 * bearerBitmask to networkTypeBitmask. 5870 */ syncBearerBitmaskAndNetworkTypeBitmask(ContentValues values)5871 private static void syncBearerBitmaskAndNetworkTypeBitmask(ContentValues values) { 5872 if (values.containsKey(NETWORK_TYPE_BITMASK)) { 5873 int convertedBitmask = convertNetworkTypeBitmaskToBearerBitmask( 5874 values.getAsInteger(NETWORK_TYPE_BITMASK)); 5875 if (values.containsKey(BEARER_BITMASK) 5876 && convertedBitmask != values.getAsInteger(BEARER_BITMASK)) { 5877 loge("Network type bitmask and bearer bitmask are not compatible."); 5878 } 5879 values.put(BEARER_BITMASK, convertNetworkTypeBitmaskToBearerBitmask( 5880 values.getAsInteger(NETWORK_TYPE_BITMASK))); 5881 } else { 5882 if (values.containsKey(BEARER_BITMASK)) { 5883 int convertedBitmask = convertBearerBitmaskToNetworkTypeBitmask( 5884 values.getAsInteger(BEARER_BITMASK)); 5885 values.put(NETWORK_TYPE_BITMASK, convertedBitmask); 5886 } 5887 } 5888 } 5889 5890 /** 5891 * Log with debug 5892 * 5893 * @param s is string log 5894 */ log(String s)5895 private static void log(String s) { 5896 Log.d(TAG, s); 5897 } 5898 loge(String s)5899 private static void loge(String s) { 5900 Log.e(TAG, s); 5901 } 5902 getMvnoTypeIntFromString(String mvnoType)5903 private static int getMvnoTypeIntFromString(String mvnoType) { 5904 String mvnoTypeString = TextUtils.isEmpty(mvnoType) ? mvnoType : mvnoType.toLowerCase(Locale.ROOT); 5905 Integer mvnoTypeInt = MVNO_TYPE_STRING_MAP.get(mvnoTypeString); 5906 return mvnoTypeInt == null ? ApnSetting.MVNO_TYPE_UNKNOWN : mvnoTypeInt; 5907 } 5908 getBitmaskFromString(String bearerList)5909 private static int getBitmaskFromString(String bearerList) { 5910 String[] bearers = bearerList.split("\\|"); 5911 int bearerBitmask = 0; 5912 for (String bearer : bearers) { 5913 int bearerInt = 0; 5914 try { 5915 bearerInt = Integer.parseInt(bearer.trim()); 5916 } catch (NumberFormatException nfe) { 5917 return 0; 5918 } 5919 5920 if (bearerInt == 0) { 5921 return 0; 5922 } 5923 bearerBitmask |= getBitmaskForTech(bearerInt); 5924 } 5925 return bearerBitmask; 5926 } 5927 5928 /** 5929 * Get the infrastructure bitmask from string 5930 * 5931 * @param infrastructureString The infrastructure list in string format. For example 5932 * {@code "cellular|satellite"}. 5933 * 5934 * @return The infrastructure bitmask. 5935 */ getInfrastructureListFromString(@onNull String infrastructureString)5936 private static int getInfrastructureListFromString(@NonNull String infrastructureString) { 5937 String[] infras = infrastructureString.split("\\|"); 5938 int infrastructureBitmask = 0; 5939 for (String infrastructure : infras) { 5940 switch (infrastructure.toLowerCase(Locale.ROOT)) { 5941 case "cellular": 5942 infrastructureBitmask |= ApnSetting.INFRASTRUCTURE_CELLULAR; 5943 break; 5944 case "satellite": 5945 infrastructureBitmask |= ApnSetting.INFRASTRUCTURE_SATELLITE; 5946 break; 5947 } 5948 } 5949 return infrastructureBitmask; 5950 } 5951 5952 /** 5953 * Transform RIL radio technology value to Network 5954 * type bitmask{@link android.telephony.TelephonyManager.NetworkTypeBitMask}. 5955 * 5956 * @param rat The RIL radio technology. 5957 * @return The network type 5958 * bitmask{@link android.telephony.TelephonyManager.NetworkTypeBitMask}. 5959 */ rilRadioTechnologyToNetworkTypeBitmask(int rat)5960 private static int rilRadioTechnologyToNetworkTypeBitmask(int rat) { 5961 switch (rat) { 5962 case RIL_RADIO_TECHNOLOGY_GPRS: 5963 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_GPRS; 5964 case RIL_RADIO_TECHNOLOGY_EDGE: 5965 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EDGE; 5966 case RIL_RADIO_TECHNOLOGY_UMTS: 5967 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UMTS; 5968 case RIL_RADIO_TECHNOLOGY_HSDPA: 5969 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA; 5970 case RIL_RADIO_TECHNOLOGY_HSUPA: 5971 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA; 5972 case RIL_RADIO_TECHNOLOGY_HSPA: 5973 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPA; 5974 case RIL_RADIO_TECHNOLOGY_IS95A: 5975 case RIL_RADIO_TECHNOLOGY_IS95B: 5976 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_CDMA; 5977 case RIL_RADIO_TECHNOLOGY_1xRTT: 5978 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT; 5979 case RIL_RADIO_TECHNOLOGY_EVDO_0: 5980 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0; 5981 case RIL_RADIO_TECHNOLOGY_EVDO_A: 5982 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A; 5983 case RIL_RADIO_TECHNOLOGY_EVDO_B: 5984 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B; 5985 case RIL_RADIO_TECHNOLOGY_EHRPD: 5986 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD; 5987 case RIL_RADIO_TECHNOLOGY_LTE: 5988 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE; 5989 case RIL_RADIO_TECHNOLOGY_HSPAP: 5990 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP; 5991 case RIL_RADIO_TECHNOLOGY_GSM: 5992 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_GSM; 5993 case RIL_RADIO_TECHNOLOGY_TD_SCDMA: 5994 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA; 5995 case RIL_RADIO_TECHNOLOGY_IWLAN: 5996 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN; 5997 case RIL_RADIO_TECHNOLOGY_LTE_CA: 5998 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA; 5999 case RIL_RADIO_TECHNOLOGY_NR: 6000 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_NR; 6001 default: 6002 return (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN; 6003 } 6004 } 6005 6006 /** 6007 * Convert network type bitmask to bearer bitmask. 6008 * 6009 * @param networkTypeBitmask The network type bitmask value 6010 * @return The bearer bitmask value. 6011 */ convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask)6012 private static int convertNetworkTypeBitmaskToBearerBitmask(int networkTypeBitmask) { 6013 if (networkTypeBitmask == 0) { 6014 return 0; 6015 } 6016 6017 int bearerBitmask = 0; 6018 for (int bearerInt = 0; bearerInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerInt++) { 6019 if (bitmaskHasTarget(networkTypeBitmask, 6020 rilRadioTechnologyToNetworkTypeBitmask(bearerInt))) { 6021 bearerBitmask |= getBitmaskForTech(bearerInt); 6022 } 6023 } 6024 return bearerBitmask; 6025 } 6026 6027 /** 6028 * Convert bearer bitmask to network type bitmask. 6029 * 6030 * @param bearerBitmask The bearer bitmask value. 6031 * @return The network type bitmask value. 6032 */ convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask)6033 private static int convertBearerBitmaskToNetworkTypeBitmask(int bearerBitmask) { 6034 if (bearerBitmask == 0) { 6035 return 0; 6036 } 6037 6038 int networkTypeBitmask = 0; 6039 for (int bearerUnitInt = 0; bearerUnitInt < NEXT_RIL_RADIO_TECHNOLOGY; bearerUnitInt++) { 6040 int bearerUnitBitmask = getBitmaskForTech(bearerUnitInt); 6041 if (bitmaskHasTarget(bearerBitmask, bearerUnitBitmask)) { 6042 networkTypeBitmask |= rilRadioTechnologyToNetworkTypeBitmask(bearerUnitInt); 6043 } 6044 } 6045 return networkTypeBitmask; 6046 } 6047 bitmaskHasTarget(int bearerBitmask, int targetBitmask)6048 private static boolean bitmaskHasTarget(int bearerBitmask, int targetBitmask) { 6049 if (bearerBitmask == 0) { 6050 return true; 6051 } else if (targetBitmask != 0) { 6052 return ((bearerBitmask & targetBitmask) != 0); 6053 } 6054 return false; 6055 } 6056 getBitmaskForTech(int radioTech)6057 private static int getBitmaskForTech(int radioTech) { 6058 if (radioTech >= 1) { 6059 return (1 << (radioTech - 1)); 6060 } 6061 return 0; 6062 } 6063 6064 /** 6065 * Migrate the old Long values{@link Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES} over to 6066 * String{@link Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_ALL_REASON} 6067 * 6068 * @param db The sqlite database to write to 6069 * @param c The {@link Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES} values in the sim info 6070 * table. 6071 */ fillInAllowedNetworkTypesStringAtCursor(SQLiteDatabase db, Cursor c)6072 public static void fillInAllowedNetworkTypesStringAtCursor(SQLiteDatabase db, Cursor c) { 6073 long allowedNetworkTypesReasonCarrier; 6074 String subId; 6075 try { 6076 allowedNetworkTypesReasonCarrier = c.getLong( 6077 c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES)); 6078 subId = c.getString(c.getColumnIndexOrThrow( 6079 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID)); 6080 } catch (IllegalArgumentException e) { 6081 Log.e(TAG, "Possible database corruption -- some columns not found."); 6082 return; 6083 } 6084 6085 if (allowedNetworkTypesReasonCarrier != -1) { 6086 ContentValues cv = new ContentValues(1); 6087 6088 cv.put(Telephony.SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 6089 "carrier=" + allowedNetworkTypesReasonCarrier); 6090 db.update(SIMINFO_TABLE, cv, 6091 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?", 6092 new String[]{subId}); 6093 } 6094 } 6095 6096 /** 6097 * Migrate the old values{@link Telephony.SimInfo#COLUMN_DATA_ENABLED_OVERRIDE_RULES} over to 6098 * String{@link Telephony.SimInfo#COLUMN_ENABLED_MOBILE_DATA_POLICIES} 6099 * 6100 * @param db The sqlite database to write to 6101 * @param c The {@link Telephony.SimInfo#COLUMN_DATA_ENABLED_OVERRIDE_RULES} values in the sim info 6102 * table. 6103 */ fillInEnabledMobileDataPoliciesAtCursor(SQLiteDatabase db, Cursor c)6104 public static void fillInEnabledMobileDataPoliciesAtCursor(SQLiteDatabase db, Cursor c) { 6105 String overrideRule; 6106 String subId; 6107 try { 6108 overrideRule = c.getString( 6109 c.getColumnIndexOrThrow(Telephony.SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES)); 6110 subId = c.getString(c.getColumnIndexOrThrow( 6111 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID)); 6112 } catch (IllegalArgumentException e) { 6113 Log.e(TAG, "COLUMN_DATA_ENABLED_OVERRIDE_RULES not found."); 6114 return; 6115 } 6116 6117 if (overrideRule != null) { 6118 ContentValues cv = new ContentValues(1); 6119 6120 // convert override rule to its corresponding mobile data policy 6121 overrideRule = overrideRule.contains("mms") ? 6122 String.valueOf(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED): ""; 6123 cv.put(Telephony.SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, overrideRule); 6124 db.update(SIMINFO_TABLE, cv, 6125 Telephony.SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=?", 6126 new String[]{subId}); 6127 } 6128 } 6129 6130 /** 6131 * Dump the database table. 6132 * 6133 * @param tableName Table name. 6134 * @param pw Print writer. 6135 */ dumpTable(@onNull String tableName, @NonNull IndentingPrintWriter pw)6136 private void dumpTable(@NonNull String tableName, @NonNull IndentingPrintWriter pw) { 6137 try (Cursor cursor = getReadableDatabase().query(false, tableName, null, 6138 null, null, null, null, null, null)) { 6139 pw.println(tableName + " table:"); 6140 pw.increaseIndent(); 6141 while (cursor != null && cursor.moveToNext()) { 6142 List<String> columnStrings = new ArrayList<>(); 6143 String str = ""; 6144 for (int i = 0; i < cursor.getColumnCount(); i++) { 6145 str = cursor.getColumnName(i) + "="; 6146 int type = cursor.getType(i); 6147 try { 6148 switch (type) { 6149 case 0 /*FIELD_TYPE_NULL*/: 6150 str += "null"; 6151 break; 6152 case 1 /*FIELD_TYPE_INTEGER*/: 6153 str += cursor.getInt(i); 6154 break; 6155 case 2 /*FIELD_TYPE_FLOAT*/: 6156 str += cursor.getFloat(i); 6157 break; 6158 case 3 /*FIELD_TYPE_STRING*/: 6159 String columnValue = cursor.getString(i); 6160 // Redact icc_id and card_id 6161 if (SIMINFO_TABLE.equals(tableName) 6162 && (Telephony.SimInfo.COLUMN_ICC_ID.equals( 6163 cursor.getColumnName(i)) 6164 || Telephony.SimInfo.COLUMN_CARD_ID.equals( 6165 cursor.getColumnName(i)))) { 6166 columnValue = SubscriptionInfo.getPrintableId(columnValue); 6167 } 6168 str += columnValue; 6169 break; 6170 case 4 /*FIELD_TYPE_BLOB*/: 6171 str += "[blob]"; 6172 break; 6173 default: 6174 str += "unknown"; 6175 break; 6176 } 6177 } catch (Exception e) { 6178 str += "exception"; 6179 } 6180 columnStrings.add(str); 6181 } 6182 pw.println(TextUtils.join(", ", columnStrings)); 6183 } 6184 pw.decreaseIndent(); 6185 } catch (Exception ex) { 6186 pw.println("Exception while dumping the table " + tableName + ", ex=" + ex); 6187 } 6188 } 6189 6190 @Override dump(FileDescriptor fd, PrintWriter printWriter, String[] args)6191 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 6192 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 6193 pw.println(TAG + ":"); 6194 pw.increaseIndent(); 6195 pw.println("Database:"); 6196 pw.increaseIndent(); 6197 dumpTable(SIMINFO_TABLE, pw); 6198 dumpTable(CARRIERS_TABLE, pw); 6199 pw.decreaseIndent(); 6200 pw.println("Local log:"); 6201 pw.increaseIndent(); 6202 mLocalLog.dump(pw); 6203 pw.decreaseIndent(); 6204 pw.decreaseIndent(); 6205 } 6206 } 6207