1 /* 2 * Copyright (c) 2015, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.phone; 18 19 import static android.service.carrier.CarrierService.ICarrierServiceWrapper.KEY_CONFIG_BUNDLE; 20 import static android.service.carrier.CarrierService.ICarrierServiceWrapper.RESULT_ERROR; 21 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.app.AppOpsManager; 25 import android.content.BroadcastReceiver; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.ServiceConnection; 31 import android.content.SharedPreferences; 32 import android.content.pm.PackageInfo; 33 import android.content.pm.PackageManager; 34 import android.os.Binder; 35 import android.os.Build; 36 import android.os.Bundle; 37 import android.os.Handler; 38 import android.os.HandlerExecutor; 39 import android.os.IBinder; 40 import android.os.Looper; 41 import android.os.Message; 42 import android.os.PersistableBundle; 43 import android.os.Process; 44 import android.os.RemoteException; 45 import android.os.ResultReceiver; 46 import android.os.UserHandle; 47 import android.preference.PreferenceManager; 48 import android.service.carrier.CarrierIdentifier; 49 import android.service.carrier.CarrierService; 50 import android.service.carrier.ICarrierService; 51 import android.telephony.CarrierConfigManager; 52 import android.telephony.SubscriptionManager; 53 import android.telephony.TelephonyFrameworkInitializer; 54 import android.telephony.TelephonyManager; 55 import android.telephony.TelephonyRegistryManager; 56 import android.text.TextUtils; 57 import android.util.ArraySet; 58 import android.util.LocalLog; 59 import android.util.Log; 60 61 import com.android.internal.annotations.VisibleForTesting; 62 import com.android.internal.telephony.ICarrierConfigLoader; 63 import com.android.internal.telephony.IccCardConstants; 64 import com.android.internal.telephony.Phone; 65 import com.android.internal.telephony.PhoneConfigurationManager; 66 import com.android.internal.telephony.PhoneFactory; 67 import com.android.internal.telephony.TelephonyPermissions; 68 import com.android.internal.telephony.subscription.SubscriptionManagerService; 69 import com.android.internal.telephony.util.ArrayUtils; 70 import com.android.internal.util.IndentingPrintWriter; 71 import com.android.telephony.Rlog; 72 73 import java.io.File; 74 import java.io.FileDescriptor; 75 import java.io.FileInputStream; 76 import java.io.FileNotFoundException; 77 import java.io.FileOutputStream; 78 import java.io.FilenameFilter; 79 import java.io.IOException; 80 import java.io.PrintWriter; 81 import java.util.ArrayList; 82 import java.util.Arrays; 83 import java.util.Collections; 84 import java.util.List; 85 import java.util.Objects; 86 import java.util.Set; 87 88 /** 89 * CarrierConfigLoader binds to privileged carrier apps to fetch carrier config overlays. 90 */ 91 public class CarrierConfigLoader extends ICarrierConfigLoader.Stub { 92 private static final String LOG_TAG = "CarrierConfigLoader"; 93 94 // Package name for platform carrier config app, bundled with system image. 95 @NonNull private final String mPlatformCarrierConfigPackage; 96 97 /** The singleton instance. */ 98 @Nullable private static CarrierConfigLoader sInstance; 99 // The context for phone app, passed from PhoneGlobals. 100 @NonNull private Context mContext; 101 102 // All the states below (array indexed by phoneId) are non-null. But the member of the array 103 // is nullable, when e.g. the config for the phone is not loaded yet 104 // Carrier configs from default app, indexed by phoneID. 105 @NonNull private PersistableBundle[] mConfigFromDefaultApp; 106 // Carrier configs from privileged carrier config app, indexed by phoneID. 107 @NonNull private PersistableBundle[] mConfigFromCarrierApp; 108 // Persistent Carrier configs that are provided via the override test API, indexed by phone ID. 109 @NonNull private PersistableBundle[] mPersistentOverrideConfigs; 110 // Carrier configs that are provided via the override test API, indexed by phone ID. 111 @NonNull private PersistableBundle[] mOverrideConfigs; 112 // Carrier configs to override code default when there is no SIM inserted 113 @NonNull private PersistableBundle mNoSimConfig; 114 // Service connection for binding to config app. 115 @NonNull private CarrierServiceConnection[] mServiceConnection; 116 // Service connection for binding to carrier config app for no SIM config. 117 @NonNull private CarrierServiceConnection[] mServiceConnectionForNoSimConfig; 118 // Whether we are bound to a service for each phone 119 @NonNull private boolean[] mServiceBound; 120 // Whether we are bound to a service for no SIM config 121 @NonNull private boolean[] mServiceBoundForNoSimConfig; 122 // Whether we have sent config change broadcast for each phone id. 123 @NonNull private boolean[] mHasSentConfigChange; 124 // Whether the broadcast was sent from EVENT_SYSTEM_UNLOCKED, to track rebroadcasts 125 @NonNull private boolean[] mFromSystemUnlocked; 126 // CarrierService change monitoring 127 @NonNull private CarrierServiceChangeCallback[] mCarrierServiceChangeCallbacks; 128 129 // Broadcast receiver for system events 130 @NonNull 131 private final BroadcastReceiver mSystemBroadcastReceiver = new ConfigLoaderBroadcastReceiver(); 132 @NonNull private final LocalLog mCarrierConfigLoadingLog = new LocalLog(100); 133 // Number of phone instances (active modem count) 134 private int mNumPhones; 135 136 137 // Message codes; see mHandler below. 138 // Request from UiccController when SIM becomes absent or error. 139 private static final int EVENT_CLEAR_CONFIG = 0; 140 // Has connected to default app. 141 private static final int EVENT_CONNECTED_TO_DEFAULT = 3; 142 // Has connected to carrier app. 143 private static final int EVENT_CONNECTED_TO_CARRIER = 4; 144 // Config has been loaded from default app (or cache). 145 private static final int EVENT_FETCH_DEFAULT_DONE = 5; 146 // Config has been loaded from carrier app (or cache). 147 private static final int EVENT_FETCH_CARRIER_DONE = 6; 148 // Attempt to fetch from default app or read from XML. 149 private static final int EVENT_DO_FETCH_DEFAULT = 7; 150 // Attempt to fetch from carrier app or read from XML. 151 private static final int EVENT_DO_FETCH_CARRIER = 8; 152 // A package has been installed, uninstalled, or updated. 153 private static final int EVENT_PACKAGE_CHANGED = 9; 154 // Bind timed out for the default app. 155 private static final int EVENT_BIND_DEFAULT_TIMEOUT = 10; 156 // Bind timed out for a carrier app. 157 private static final int EVENT_BIND_CARRIER_TIMEOUT = 11; 158 // Check if the system fingerprint has changed. 159 private static final int EVENT_CHECK_SYSTEM_UPDATE = 12; 160 // Rerun carrier config binding after system is unlocked. 161 private static final int EVENT_SYSTEM_UNLOCKED = 13; 162 // Fetching config timed out from the default app. 163 private static final int EVENT_FETCH_DEFAULT_TIMEOUT = 14; 164 // Fetching config timed out from a carrier app. 165 private static final int EVENT_FETCH_CARRIER_TIMEOUT = 15; 166 // SubscriptionManagerService has finished updating the sub for the carrier config. 167 private static final int EVENT_SUBSCRIPTION_INFO_UPDATED = 16; 168 // Multi-SIM config changed. 169 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 17; 170 // Attempt to fetch from default app or read from XML for no SIM case. 171 private static final int EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG = 18; 172 // No SIM config has been loaded from default app (or cache). 173 private static final int EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE = 19; 174 // Has connected to default app for no SIM config. 175 private static final int EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG = 20; 176 // Bind timed out for the default app when trying to fetch no SIM config. 177 private static final int EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 21; 178 // Fetching config timed out from the default app for no SIM config. 179 private static final int EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT = 22; 180 // NOTE: any new EVENT_* values must be added to method eventToString(). 181 182 private static final int BIND_TIMEOUT_MILLIS = 30000; 183 184 // Keys used for saving and restoring config bundle from file. 185 private static final String KEY_VERSION = "__carrier_config_package_version__"; 186 187 private static final String OVERRIDE_PACKAGE_ADDITION = "-override"; 188 189 // SharedPreferences key for last known build fingerprint. 190 private static final String KEY_FINGERPRINT = "build_fingerprint"; 191 192 // Argument for #dump that indicates we should also call the default and specified carrier 193 // service's #dump method. In multi-SIM devices, it's possible that carrier A is on SIM 1 and 194 // carrier B is on SIM 2, in which case we should not dump carrier B's service when carrier A 195 // requested the dump. 196 private static final String DUMP_ARG_REQUESTING_PACKAGE = "--requesting-package"; 197 198 // Configs that should always be included when clients calls getConfig[ForSubId] with specified 199 // keys (even configs are not explicitly specified). Those configs have special purpose for the 200 // carrier config APIs to work correctly. 201 private static final String[] CONFIG_SUBSET_METADATA_KEYS = new String[] { 202 CarrierConfigManager.KEY_CARRIER_CONFIG_VERSION_STRING, 203 CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL 204 }; 205 206 // Handler to process various events. 207 // 208 // For each phoneId, the event sequence should be: 209 // fetch default, connected to default, fetch default (async), fetch default done, 210 // fetch carrier, connected to carrier, fetch carrier (async), fetch carrier done. 211 // 212 // If there is a saved config file for either the default app or the carrier app, we skip 213 // binding to the app and go straight from fetch to loaded. 214 // 215 // At any time, at most one connection is active. If events are not in this order, previous 216 // connection will be unbound, so only latest event takes effect. 217 // 218 // We broadcast ACTION_CARRIER_CONFIG_CHANGED after: 219 // 1. loading from carrier app (even if read from a file) 220 // 2. loading from default app if there is no carrier app (even if read from a file) 221 // 3. clearing config (e.g. due to sim removal) 222 // 4. encountering bind or IPC error 223 private class ConfigHandler extends Handler { ConfigHandler(@onNull Looper looper)224 ConfigHandler(@NonNull Looper looper) { 225 super(looper); 226 } 227 228 @Override handleMessage(@onNull Message msg)229 public void handleMessage(@NonNull Message msg) { 230 final int phoneId = msg.arg1; 231 logdWithLocalLog("mHandler: " + eventToString(msg.what) + " phoneId: " + phoneId); 232 if (!SubscriptionManager.isValidPhoneId(phoneId) 233 && msg.what != EVENT_MULTI_SIM_CONFIG_CHANGED) { 234 return; 235 } 236 switch (msg.what) { 237 case EVENT_CLEAR_CONFIG: { 238 clearConfigForPhone(phoneId, true); 239 break; 240 } 241 242 case EVENT_SYSTEM_UNLOCKED: { 243 for (int i = 0; i < mNumPhones; ++i) { 244 // When the user unlocks the device, send the broadcast again (with a 245 // rebroadcast extra) if we have sent it before unlock. This will avoid 246 // trying to load the carrier config when the SIM is still loading when the 247 // unlock happens. 248 if (mHasSentConfigChange[i]) { 249 logdWithLocalLog("System unlocked"); 250 mFromSystemUnlocked[i] = true; 251 updateConfigForPhoneId(i); 252 } 253 } 254 break; 255 } 256 257 case EVENT_PACKAGE_CHANGED: { 258 final String carrierPackageName = (String) msg.obj; 259 // Always clear up the cache and re-load config from scratch since the carrier 260 // service change is reliable and specific to the phoneId now. 261 clearCachedConfigForPackage(carrierPackageName); 262 logdWithLocalLog("Package changed: " + carrierPackageName 263 + ", phone=" + phoneId); 264 updateConfigForPhoneId(phoneId); 265 break; 266 } 267 268 case EVENT_DO_FETCH_DEFAULT: { 269 // Clear in-memory cache for carrier app config, so when carrier app gets 270 // uninstalled, no stale config is left. 271 if (mConfigFromCarrierApp[phoneId] != null 272 && getCarrierPackageForPhoneId(phoneId) == null) { 273 mConfigFromCarrierApp[phoneId] = null; 274 } 275 // Restore persistent override values. 276 PersistableBundle config = restoreConfigFromXml( 277 mPlatformCarrierConfigPackage, OVERRIDE_PACKAGE_ADDITION, phoneId); 278 if (config != null) { 279 logd("Loaded persistent override config from XML. package=" 280 + mPlatformCarrierConfigPackage 281 + " phoneId=" + phoneId); 282 mPersistentOverrideConfigs[phoneId] = config; 283 } 284 285 config = restoreConfigFromXml(mPlatformCarrierConfigPackage, "", phoneId); 286 if (config != null) { 287 logd( 288 "Loaded config from XML. package=" 289 + mPlatformCarrierConfigPackage 290 + " phoneId=" 291 + phoneId); 292 mConfigFromDefaultApp[phoneId] = config; 293 Message newMsg = obtainMessage(EVENT_FETCH_DEFAULT_DONE, phoneId, -1); 294 newMsg.getData().putBoolean("loaded_from_xml", true); 295 mHandler.sendMessage(newMsg); 296 } else { 297 // No cached config, so fetch it from the default app. 298 if (bindToConfigPackage( 299 mPlatformCarrierConfigPackage, 300 phoneId, 301 EVENT_CONNECTED_TO_DEFAULT)) { 302 sendMessageDelayed( 303 obtainMessage(EVENT_BIND_DEFAULT_TIMEOUT, phoneId, -1 /*arg2*/, 304 getMessageToken(phoneId)), 305 BIND_TIMEOUT_MILLIS); 306 } else { 307 // Put a stub bundle in place so that the rest of the logic continues 308 // smoothly. 309 mConfigFromDefaultApp[phoneId] = new PersistableBundle(); 310 // Send broadcast if bind fails. 311 updateSubscriptionDatabase(phoneId); 312 // TODO: We *must* call unbindService even if bindService returns false. 313 // (And possibly if SecurityException was thrown.) 314 loge("binding to default app: " 315 + mPlatformCarrierConfigPackage + " fails"); 316 } 317 } 318 break; 319 } 320 321 case EVENT_CONNECTED_TO_DEFAULT: { 322 removeMessages(EVENT_BIND_DEFAULT_TIMEOUT, getMessageToken(phoneId)); 323 final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj; 324 // If new service connection has been created, unbind. 325 if (mServiceConnection[phoneId] != conn || conn.service == null) { 326 unbindIfBound(mContext, conn, phoneId); 327 break; 328 } 329 final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId); 330 // ResultReceiver callback will execute in this Handler's thread. 331 final ResultReceiver resultReceiver = 332 new ResultReceiver(this) { 333 @Override 334 public void onReceiveResult(int resultCode, Bundle resultData) { 335 unbindIfBound(mContext, conn, phoneId); 336 removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT, 337 getMessageToken(phoneId)); 338 // If new service connection has been created, this is stale. 339 if (mServiceConnection[phoneId] != conn) { 340 loge("Received response for stale request."); 341 return; 342 } 343 if (resultCode == RESULT_ERROR || resultData == null) { 344 // On error, abort config fetching. 345 loge("Failed to get carrier config"); 346 updateSubscriptionDatabase(phoneId); 347 return; 348 } 349 PersistableBundle config = 350 resultData.getParcelable(KEY_CONFIG_BUNDLE); 351 saveConfigToXml(mPlatformCarrierConfigPackage, "", phoneId, 352 carrierId, config); 353 mConfigFromDefaultApp[phoneId] = config; 354 sendMessage( 355 obtainMessage( 356 EVENT_FETCH_DEFAULT_DONE, phoneId, -1)); 357 } 358 }; 359 // Now fetch the config asynchronously from the ICarrierService. 360 try { 361 ICarrierService carrierService = 362 ICarrierService.Stub.asInterface(conn.service); 363 carrierService.getCarrierConfig(phoneId, carrierId, resultReceiver); 364 logdWithLocalLog("Fetch config for default app: " 365 + mPlatformCarrierConfigPackage 366 + " carrierid: " + carrierId.toString()); 367 } catch (RemoteException e) { 368 loge("Failed to get carrier config from default app: " + 369 mPlatformCarrierConfigPackage + " err: " + e.toString()); 370 unbindIfBound(mContext, conn, phoneId); 371 break; // So we don't set a timeout. 372 } 373 sendMessageDelayed( 374 obtainMessage(EVENT_FETCH_DEFAULT_TIMEOUT, phoneId, -1 /*arg2*/, 375 getMessageToken(phoneId)), 376 BIND_TIMEOUT_MILLIS); 377 break; 378 } 379 380 case EVENT_BIND_DEFAULT_TIMEOUT: 381 case EVENT_FETCH_DEFAULT_TIMEOUT: { 382 loge("Bind/fetch time out from " + mPlatformCarrierConfigPackage); 383 removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT, getMessageToken(phoneId)); 384 // If we attempted to bind to the app, but the service connection is null due to 385 // the race condition that clear config event happens before bind/fetch complete 386 // then config was cleared while we were waiting and we should not continue. 387 if (mServiceConnection[phoneId] != null) { 388 // If a ResponseReceiver callback is in the queue when this happens, we will 389 // unbind twice and throw an exception. 390 unbindIfBound(mContext, mServiceConnection[phoneId], phoneId); 391 broadcastConfigChangedIntent(phoneId); 392 } 393 // Put a stub bundle in place so that the rest of the logic continues smoothly. 394 mConfigFromDefaultApp[phoneId] = new PersistableBundle(); 395 updateSubscriptionDatabase(phoneId); 396 break; 397 } 398 399 case EVENT_FETCH_DEFAULT_DONE: { 400 // If we attempted to bind to the app, but the service connection is null, then 401 // config was cleared while we were waiting and we should not continue. 402 if (!msg.getData().getBoolean("loaded_from_xml", false) 403 && mServiceConnection[phoneId] == null) { 404 break; 405 } 406 final String carrierPackageName = getCarrierPackageForPhoneId(phoneId); 407 if (carrierPackageName != null) { 408 logd("Found carrier config app: " + carrierPackageName); 409 sendMessage(obtainMessage(EVENT_DO_FETCH_CARRIER, phoneId, -1)); 410 } else { 411 updateSubscriptionDatabase(phoneId); 412 } 413 break; 414 } 415 416 case EVENT_DO_FETCH_CARRIER: { 417 final String carrierPackageName = getCarrierPackageForPhoneId(phoneId); 418 final PersistableBundle config = 419 restoreConfigFromXml(carrierPackageName, "", phoneId); 420 if (config != null) { 421 logd( 422 "Loaded config from XML. package=" 423 + carrierPackageName 424 + " phoneId=" 425 + phoneId); 426 mConfigFromCarrierApp[phoneId] = config; 427 Message newMsg = obtainMessage(EVENT_FETCH_CARRIER_DONE, phoneId, -1); 428 newMsg.getData().putBoolean("loaded_from_xml", true); 429 sendMessage(newMsg); 430 } else { 431 // No cached config, so fetch it from a carrier app. 432 if (carrierPackageName != null && bindToConfigPackage(carrierPackageName, 433 phoneId, EVENT_CONNECTED_TO_CARRIER)) { 434 sendMessageDelayed( 435 obtainMessage(EVENT_BIND_CARRIER_TIMEOUT, phoneId, -1 /*arg2*/, 436 getMessageToken(phoneId)), 437 BIND_TIMEOUT_MILLIS); 438 } else { 439 // Put a stub bundle in place so that the rest of the logic continues 440 // smoothly. 441 mConfigFromCarrierApp[phoneId] = new PersistableBundle(); 442 // Send broadcast if bind fails. 443 broadcastConfigChangedIntent(phoneId); 444 loge("Bind to carrier app: " + carrierPackageName + " fails"); 445 updateSubscriptionDatabase(phoneId); 446 } 447 } 448 break; 449 } 450 451 case EVENT_CONNECTED_TO_CARRIER: { 452 removeMessages(EVENT_BIND_CARRIER_TIMEOUT, getMessageToken(phoneId)); 453 final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj; 454 // If new service connection has been created, unbind. 455 if (mServiceConnection[phoneId] != conn || conn.service == null) { 456 unbindIfBound(mContext, conn, phoneId); 457 break; 458 } 459 final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId); 460 // ResultReceiver callback will execute in this Handler's thread. 461 final ResultReceiver resultReceiver = 462 new ResultReceiver(this) { 463 @Override 464 public void onReceiveResult(int resultCode, Bundle resultData) { 465 unbindIfBound(mContext, conn, phoneId); 466 removeMessages(EVENT_FETCH_CARRIER_TIMEOUT, 467 getMessageToken(phoneId)); 468 // If new service connection has been created, this is stale. 469 if (mServiceConnection[phoneId] != conn) { 470 loge("Received response for stale request."); 471 return; 472 } 473 if (resultCode == RESULT_ERROR || resultData == null) { 474 // On error, abort config fetching. 475 loge("Failed to get carrier config from carrier app: " 476 + getCarrierPackageForPhoneId(phoneId)); 477 broadcastConfigChangedIntent(phoneId); 478 updateSubscriptionDatabase(phoneId); 479 return; 480 } 481 PersistableBundle config = 482 resultData.getParcelable(KEY_CONFIG_BUNDLE); 483 saveConfigToXml(getCarrierPackageForPhoneId(phoneId), "", 484 phoneId, carrierId, config); 485 if (config != null) { 486 mConfigFromCarrierApp[phoneId] = config; 487 } else { 488 logdWithLocalLog("Config from carrier app is null " 489 + "for phoneId " + phoneId); 490 // Put a stub bundle in place so that the rest of the logic 491 // continues smoothly. 492 mConfigFromCarrierApp[phoneId] = new PersistableBundle(); 493 } 494 sendMessage( 495 obtainMessage( 496 EVENT_FETCH_CARRIER_DONE, phoneId, -1)); 497 } 498 }; 499 // Now fetch the config asynchronously from the ICarrierService. 500 try { 501 ICarrierService carrierService = 502 ICarrierService.Stub.asInterface(conn.service); 503 carrierService.getCarrierConfig(phoneId, carrierId, resultReceiver); 504 logdWithLocalLog("Fetch config for carrier app: " 505 + getCarrierPackageForPhoneId(phoneId) 506 + " carrierid: " + carrierId.toString()); 507 } catch (RemoteException e) { 508 loge("Failed to get carrier config: " + e.toString()); 509 unbindIfBound(mContext, conn, phoneId); 510 break; // So we don't set a timeout. 511 } 512 sendMessageDelayed( 513 obtainMessage(EVENT_FETCH_CARRIER_TIMEOUT, phoneId, -1 /*arg2*/, 514 getMessageToken(phoneId)), 515 BIND_TIMEOUT_MILLIS); 516 break; 517 } 518 519 case EVENT_BIND_CARRIER_TIMEOUT: 520 case EVENT_FETCH_CARRIER_TIMEOUT: { 521 loge("Bind/fetch from carrier app timeout, package=" 522 + getCarrierPackageForPhoneId(phoneId)); 523 removeMessages(EVENT_FETCH_CARRIER_TIMEOUT, getMessageToken(phoneId)); 524 // If we attempted to bind to the app, but the service connection is null due to 525 // the race condition that clear config event happens before bind/fetch complete 526 // then config was cleared while we were waiting and we should not continue. 527 if (mServiceConnection[phoneId] != null) { 528 // If a ResponseReceiver callback is in the queue when this happens, we will 529 // unbind twice and throw an exception. 530 unbindIfBound(mContext, mServiceConnection[phoneId], phoneId); 531 broadcastConfigChangedIntent(phoneId); 532 } 533 // Put a stub bundle in place so that the rest of the logic continues smoothly. 534 mConfigFromCarrierApp[phoneId] = new PersistableBundle(); 535 updateSubscriptionDatabase(phoneId); 536 break; 537 } 538 case EVENT_FETCH_CARRIER_DONE: { 539 // If we attempted to bind to the app, but the service connection is null, then 540 // config was cleared while we were waiting and we should not continue. 541 if (!msg.getData().getBoolean("loaded_from_xml", false) 542 && mServiceConnection[phoneId] == null) { 543 break; 544 } 545 updateSubscriptionDatabase(phoneId); 546 break; 547 } 548 549 case EVENT_CHECK_SYSTEM_UPDATE: { 550 SharedPreferences sharedPrefs = 551 PreferenceManager.getDefaultSharedPreferences(mContext); 552 final String lastFingerprint = sharedPrefs.getString(KEY_FINGERPRINT, null); 553 if (!Build.FINGERPRINT.equals(lastFingerprint)) { 554 logd( 555 "Build fingerprint changed. old: " 556 + lastFingerprint 557 + " new: " 558 + Build.FINGERPRINT); 559 clearCachedConfigForPackage(null); 560 sharedPrefs 561 .edit() 562 .putString(KEY_FINGERPRINT, Build.FINGERPRINT) 563 .apply(); 564 } 565 break; 566 } 567 568 case EVENT_SUBSCRIPTION_INFO_UPDATED: 569 broadcastConfigChangedIntent(phoneId); 570 break; 571 case EVENT_MULTI_SIM_CONFIG_CHANGED: 572 onMultiSimConfigChanged(); 573 break; 574 575 case EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG: { 576 PersistableBundle config = 577 restoreNoSimConfigFromXml(mPlatformCarrierConfigPackage); 578 579 if (config != null) { 580 logd("Loaded no SIM config from XML. package=" 581 + mPlatformCarrierConfigPackage); 582 mNoSimConfig = config; 583 sendMessage( 584 obtainMessage( 585 EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE, 586 phoneId, -1)); 587 } else { 588 // No cached config, so fetch it from the default app. 589 if (bindToConfigPackage( 590 mPlatformCarrierConfigPackage, 591 phoneId, 592 EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG)) { 593 sendMessageDelayed( 594 obtainMessage( 595 EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT, 596 phoneId, -1), BIND_TIMEOUT_MILLIS); 597 } else { 598 broadcastConfigChangedIntent(phoneId, false); 599 // TODO: We *must* call unbindService even if bindService returns false. 600 // (And possibly if SecurityException was thrown.) 601 loge("binding to default app to fetch no SIM config: " 602 + mPlatformCarrierConfigPackage + " fails"); 603 } 604 } 605 break; 606 } 607 608 case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE: { 609 broadcastConfigChangedIntent(phoneId, false); 610 break; 611 } 612 613 case EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT: 614 case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT: { 615 loge("Bind/fetch time out for no SIM config from " 616 + mPlatformCarrierConfigPackage); 617 removeMessages(EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT); 618 // If we attempted to bind to the app, but the service connection is null due to 619 // the race condition that clear config event happens before bind/fetch complete 620 // then config was cleared while we were waiting and we should not continue. 621 if (mServiceConnectionForNoSimConfig[phoneId] != null) { 622 // If a ResponseReceiver callback is in the queue when this happens, we will 623 // unbind twice and throw an exception. 624 unbindIfBoundForNoSimConfig(mContext, 625 mServiceConnectionForNoSimConfig[phoneId], phoneId); 626 } 627 broadcastConfigChangedIntent(phoneId, false); 628 break; 629 } 630 631 case EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG: { 632 removeMessages(EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT); 633 final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj; 634 // If new service connection has been created, unbind. 635 if (mServiceConnectionForNoSimConfig[phoneId] != conn || conn.service == null) { 636 unbindIfBoundForNoSimConfig(mContext, conn, phoneId); 637 break; 638 } 639 640 // ResultReceiver callback will execute in this Handler's thread. 641 final ResultReceiver resultReceiver = 642 new ResultReceiver(this) { 643 @Override 644 public void onReceiveResult(int resultCode, Bundle resultData) { 645 unbindIfBoundForNoSimConfig(mContext, conn, phoneId); 646 // If new service connection has been created, this is stale. 647 if (mServiceConnectionForNoSimConfig[phoneId] != conn) { 648 loge("Received response for stale request."); 649 return; 650 } 651 removeMessages(EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT); 652 if (resultCode == RESULT_ERROR || resultData == null) { 653 // On error, abort config fetching. 654 loge("Failed to get no SIM carrier config"); 655 return; 656 } 657 PersistableBundle config = 658 resultData.getParcelable(KEY_CONFIG_BUNDLE); 659 saveNoSimConfigToXml(mPlatformCarrierConfigPackage, config); 660 mNoSimConfig = config; 661 sendMessage( 662 obtainMessage( 663 EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE, 664 phoneId, -1)); 665 } 666 }; 667 // Now fetch the config asynchronously from the ICarrierService. 668 try { 669 ICarrierService carrierService = 670 ICarrierService.Stub.asInterface(conn.service); 671 carrierService.getCarrierConfig(phoneId, null, resultReceiver); 672 logdWithLocalLog("Fetch no sim config from default app: " 673 + mPlatformCarrierConfigPackage); 674 } catch (RemoteException e) { 675 loge("Failed to get no sim carrier config from default app: " + 676 mPlatformCarrierConfigPackage + " err: " + e.toString()); 677 unbindIfBoundForNoSimConfig(mContext, conn, phoneId); 678 break; // So we don't set a timeout. 679 } 680 sendMessageDelayed( 681 obtainMessage( 682 EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT, 683 phoneId, -1), BIND_TIMEOUT_MILLIS); 684 break; 685 } 686 } 687 } 688 } 689 690 @NonNull private final Handler mHandler; 691 692 /** 693 * Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast 694 * receiver for relevant events. 695 */ 696 @VisibleForTesting CarrierConfigLoader(@onNull Context context, @NonNull Looper looper)697 /* package */ CarrierConfigLoader(@NonNull Context context, @NonNull Looper looper) { 698 mContext = context; 699 mPlatformCarrierConfigPackage = 700 mContext.getString(R.string.platform_carrier_config_package); 701 mHandler = new ConfigHandler(looper); 702 703 IntentFilter systemEventsFilter = new IntentFilter(); 704 systemEventsFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 705 context.registerReceiver(mSystemBroadcastReceiver, systemEventsFilter); 706 707 mNumPhones = TelephonyManager.from(context).getActiveModemCount(); 708 mConfigFromDefaultApp = new PersistableBundle[mNumPhones]; 709 mConfigFromCarrierApp = new PersistableBundle[mNumPhones]; 710 mPersistentOverrideConfigs = new PersistableBundle[mNumPhones]; 711 mOverrideConfigs = new PersistableBundle[mNumPhones]; 712 mNoSimConfig = new PersistableBundle(); 713 mServiceConnection = new CarrierServiceConnection[mNumPhones]; 714 mServiceBound = new boolean[mNumPhones]; 715 mHasSentConfigChange = new boolean[mNumPhones]; 716 mFromSystemUnlocked = new boolean[mNumPhones]; 717 mServiceConnectionForNoSimConfig = new CarrierServiceConnection[mNumPhones]; 718 mServiceBoundForNoSimConfig = new boolean[mNumPhones]; 719 mCarrierServiceChangeCallbacks = new CarrierServiceChangeCallback[mNumPhones]; 720 for (int phoneId = 0; phoneId < mNumPhones; phoneId++) { 721 mCarrierServiceChangeCallbacks[phoneId] = new CarrierServiceChangeCallback(phoneId); 722 TelephonyManager.from(context).registerCarrierPrivilegesCallback(phoneId, 723 new HandlerExecutor(mHandler), mCarrierServiceChangeCallbacks[phoneId]); 724 } 725 logd("CarrierConfigLoader has started"); 726 727 PhoneConfigurationManager.registerForMultiSimConfigChange( 728 mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 729 730 mHandler.sendEmptyMessage(EVENT_CHECK_SYSTEM_UPDATE); 731 } 732 733 /** 734 * Initialize the singleton CarrierConfigLoader instance. 735 * 736 * This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}. 737 */ 738 @NonNull init(@onNull Context context)739 /* package */ static CarrierConfigLoader init(@NonNull Context context) { 740 synchronized (CarrierConfigLoader.class) { 741 if (sInstance == null) { 742 sInstance = new CarrierConfigLoader(context, Looper.myLooper()); 743 // Make this service available through ServiceManager. 744 TelephonyFrameworkInitializer.getTelephonyServiceManager() 745 .getCarrierConfigServiceRegisterer().register(sInstance); 746 } else { 747 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance); 748 } 749 return sInstance; 750 } 751 } 752 753 @VisibleForTesting clearConfigForPhone(int phoneId, boolean fetchNoSimConfig)754 /* package */ void clearConfigForPhone(int phoneId, boolean fetchNoSimConfig) { 755 /* Ignore clear configuration request if device is being shutdown. */ 756 Phone phone = PhoneFactory.getPhone(phoneId); 757 if (phone != null) { 758 if (phone.isShuttingDown()) { 759 return; 760 } 761 } 762 763 if (mConfigFromDefaultApp.length <= phoneId) { 764 Log.wtf(LOG_TAG, "Invalid phone id " + phoneId); 765 return; 766 } 767 768 mConfigFromDefaultApp[phoneId] = null; 769 mConfigFromCarrierApp[phoneId] = null; 770 mServiceConnection[phoneId] = null; 771 mHasSentConfigChange[phoneId] = false; 772 773 if (fetchNoSimConfig) { 774 // To fetch no SIM config 775 mHandler.sendMessage( 776 mHandler.obtainMessage( 777 EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG, phoneId, -1)); 778 } 779 } 780 updateSubscriptionDatabase(int phoneId)781 private void updateSubscriptionDatabase(int phoneId) { 782 logd("updateSubscriptionDatabase: phoneId=" + phoneId); 783 String configPackageName; 784 PersistableBundle configToSend; 785 int carrierId = getSpecificCarrierIdForPhoneId(phoneId); 786 // Prefer the carrier privileged carrier app, but if there is not one, use the platform 787 // default carrier app. 788 if (mConfigFromCarrierApp[phoneId] != null) { 789 configPackageName = getCarrierPackageForPhoneId(phoneId); 790 configToSend = mConfigFromCarrierApp[phoneId]; 791 } else { 792 configPackageName = mPlatformCarrierConfigPackage; 793 configToSend = mConfigFromDefaultApp[phoneId]; 794 } 795 796 if (configToSend == null) { 797 configToSend = new PersistableBundle(); 798 } 799 800 // mOverrideConfigs is for testing. And it will override current configs. 801 PersistableBundle config = mOverrideConfigs[phoneId]; 802 if (config != null) { 803 configToSend = new PersistableBundle(configToSend); 804 configToSend.putAll(config); 805 } 806 807 SubscriptionManagerService.getInstance().updateSubscriptionByCarrierConfig( 808 phoneId, configPackageName, configToSend, 809 () -> mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1) 810 .sendToTarget()); 811 } 812 broadcastConfigChangedIntent(int phoneId)813 private void broadcastConfigChangedIntent(int phoneId) { 814 broadcastConfigChangedIntent(phoneId, true); 815 } 816 broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra)817 private void broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra) { 818 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 819 int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 820 int specificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 821 822 Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 823 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 824 Intent.FLAG_RECEIVER_FOREGROUND); 825 if (addSubIdExtra) { 826 int simApplicationState = getSimApplicationStateForPhone(phoneId); 827 // Include subId/carrier id extra only if SIM records are loaded 828 if (simApplicationState != TelephonyManager.SIM_STATE_UNKNOWN 829 && simApplicationState != TelephonyManager.SIM_STATE_NOT_READY) { 830 subId = SubscriptionManager.getSubscriptionId(phoneId); 831 carrierId = getCarrierIdForPhoneId(phoneId); 832 specificCarrierId = getSpecificCarrierIdForPhoneId(phoneId); 833 intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID, specificCarrierId); 834 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId); 835 intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, carrierId); 836 } 837 } 838 intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId); 839 intent.putExtra(CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, 840 mFromSystemUnlocked[phoneId]); 841 842 TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class); 843 // Unlike broadcast, we wouldn't notify registrants on carrier config change when device is 844 // unlocked. Only real carrier config change will send the notification to registrants. 845 if (trm != null && !mFromSystemUnlocked[phoneId]) { 846 trm.notifyCarrierConfigChanged(phoneId, subId, carrierId, specificCarrierId); 847 } 848 849 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 850 851 if (SubscriptionManager.isValidSubscriptionId(subId)) { 852 logd("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId + ", subId=" + subId); 853 } else { 854 logd("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId); 855 } 856 mHasSentConfigChange[phoneId] = true; 857 mFromSystemUnlocked[phoneId] = false; 858 } 859 getSimApplicationStateForPhone(int phoneId)860 private int getSimApplicationStateForPhone(int phoneId) { 861 int simApplicationState = TelephonyManager.SIM_STATE_UNKNOWN; 862 int subId = SubscriptionManager.getSubscriptionId(phoneId); 863 if (SubscriptionManager.isValidSubscriptionId(subId)) { 864 TelephonyManager telMgr = TelephonyManager.from(mContext) 865 .createForSubscriptionId(subId); 866 simApplicationState = telMgr.getSimApplicationState(); 867 } 868 return simApplicationState; 869 } 870 871 /** Binds to the default or carrier config app. */ bindToConfigPackage(@onNull String pkgName, int phoneId, int eventId)872 private boolean bindToConfigPackage(@NonNull String pkgName, int phoneId, int eventId) { 873 logdWithLocalLog("Binding to " + pkgName + " for phone " + phoneId); 874 Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE); 875 carrierService.setPackage(pkgName); 876 CarrierServiceConnection serviceConnection = new CarrierServiceConnection( 877 phoneId, pkgName, eventId); 878 if (eventId == EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG) { 879 mServiceConnectionForNoSimConfig[phoneId] = serviceConnection; 880 } else { 881 mServiceConnection[phoneId] = serviceConnection; 882 } 883 try { 884 if (mContext.bindService(carrierService, serviceConnection, 885 Context.BIND_AUTO_CREATE)) { 886 if (eventId == EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG) { 887 mServiceBoundForNoSimConfig[phoneId] = true; 888 } else { 889 mServiceBound[phoneId] = true; 890 } 891 return true; 892 } else { 893 return false; 894 } 895 } catch (SecurityException ex) { 896 return false; 897 } 898 } 899 900 @VisibleForTesting 901 @NonNull getCarrierIdentifierForPhoneId(int phoneId)902 /* package */ CarrierIdentifier getCarrierIdentifierForPhoneId(int phoneId) { 903 String mcc = ""; 904 String mnc = ""; 905 String imsi = ""; 906 String gid1 = ""; 907 String gid2 = ""; 908 String spn = TelephonyManager.from(mContext).getSimOperatorNameForPhone(phoneId); 909 String simOperator = TelephonyManager.from(mContext).getSimOperatorNumericForPhone(phoneId); 910 int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 911 int specificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 912 // A valid simOperator should be 5 or 6 digits, depending on the length of the MNC. 913 if (simOperator != null && simOperator.length() >= 3) { 914 mcc = simOperator.substring(0, 3); 915 mnc = simOperator.substring(3); 916 } 917 Phone phone = PhoneFactory.getPhone(phoneId); 918 if (phone != null) { 919 imsi = phone.getSubscriberId(); 920 gid1 = phone.getGroupIdLevel1(); 921 gid2 = phone.getGroupIdLevel2(); 922 carrierId = phone.getCarrierId(); 923 specificCarrierId = phone.getSpecificCarrierId(); 924 } 925 return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2, carrierId, specificCarrierId); 926 } 927 928 /** Returns the package name of a privileged carrier app, or null if there is none. */ 929 @Nullable getCarrierPackageForPhoneId(int phoneId)930 private String getCarrierPackageForPhoneId(int phoneId) { 931 final long token = Binder.clearCallingIdentity(); 932 try { 933 return TelephonyManager.from(mContext) 934 .getCarrierServicePackageNameForLogicalSlot(phoneId); 935 } finally { 936 Binder.restoreCallingIdentity(token); 937 } 938 } 939 940 @Nullable getIccIdForPhoneId(int phoneId)941 private String getIccIdForPhoneId(int phoneId) { 942 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 943 return null; 944 } 945 Phone phone = PhoneFactory.getPhone(phoneId); 946 if (phone == null) { 947 return null; 948 } 949 return phone.getIccSerialNumber(); 950 } 951 952 /** 953 * Get the sim specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()} 954 */ getSpecificCarrierIdForPhoneId(int phoneId)955 private int getSpecificCarrierIdForPhoneId(int phoneId) { 956 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 957 return TelephonyManager.UNKNOWN_CARRIER_ID; 958 } 959 Phone phone = PhoneFactory.getPhone(phoneId); 960 if (phone == null) { 961 return TelephonyManager.UNKNOWN_CARRIER_ID; 962 } 963 return phone.getSpecificCarrierId(); 964 } 965 966 /** 967 * Get the sim carrier id {@link TelephonyManager#getSimCarrierId() } 968 */ getCarrierIdForPhoneId(int phoneId)969 private int getCarrierIdForPhoneId(int phoneId) { 970 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 971 return TelephonyManager.UNKNOWN_CARRIER_ID; 972 } 973 Phone phone = PhoneFactory.getPhone(phoneId); 974 if (phone == null) { 975 return TelephonyManager.UNKNOWN_CARRIER_ID; 976 } 977 return phone.getCarrierId(); 978 } 979 980 /** 981 * Writes a bundle to an XML file. 982 * 983 * The bundle will be written to a file named after the package name, ICCID and 984 * specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()}. the same carrier 985 * should have a single copy of XML file named after carrier id. However, it's still possible 986 * that platform doesn't recognize the current sim carrier, we will use iccid + carrierid as 987 * the canonical file name. carrierid can also handle the cases SIM OTA resolves to different 988 * carrier while iccid remains the same. 989 * 990 * The file can be restored later with {@link @restoreConfigFromXml}. The XML output will 991 * include the bundle and the current version of the specified package. 992 * 993 * In case of errors or invalid input, no file will be written. 994 * 995 * @param packageName the name of the package from which we fetched this bundle. 996 * @param extraString An extra string to be used in the XML file name. 997 * @param phoneId the phone ID. 998 * @param carrierId contains all carrier-identifying information. 999 * @param config the bundle to be written. Null will be treated as an empty bundle. 1000 * @param isNoSimConfig whether this is invoked for noSimConfig or not. 1001 */ saveConfigToXml(@ullable String packageName, @NonNull String extraString, int phoneId, @Nullable CarrierIdentifier carrierId, @NonNull PersistableBundle config, boolean isNoSimConfig)1002 private void saveConfigToXml(@Nullable String packageName, @NonNull String extraString, 1003 int phoneId, @Nullable CarrierIdentifier carrierId, @NonNull PersistableBundle config, 1004 boolean isNoSimConfig) { 1005 if (packageName == null) { 1006 loge("Cannot save config with null packageName"); 1007 return; 1008 } 1009 1010 String fileName; 1011 if (isNoSimConfig) { 1012 fileName = getFilenameForNoSimConfig(packageName); 1013 } else { 1014 if (TelephonyManager.getSimStateForSlotIndex(phoneId) 1015 != TelephonyManager.SIM_STATE_LOADED) { 1016 loge("Skip save config because SIM records are not loaded."); 1017 return; 1018 } 1019 1020 final String iccid = getIccIdForPhoneId(phoneId); 1021 final int cid = carrierId != null ? carrierId.getSpecificCarrierId() 1022 : TelephonyManager.UNKNOWN_CARRIER_ID; 1023 if (iccid == null) { 1024 loge("Cannot save config with null iccid."); 1025 return; 1026 } 1027 fileName = getFilenameForConfig(packageName, extraString, iccid, cid); 1028 } 1029 1030 // b/32668103 Only save to file if config isn't empty. 1031 // In case of failure, not caching an empty bundle will 1032 // try loading config again on next power on or sim loaded. 1033 // Downside is for genuinely empty bundle, will bind and load 1034 // on every power on. 1035 if (config == null || config.isEmpty()) { 1036 return; 1037 } 1038 1039 final String version = getPackageVersion(packageName); 1040 if (version == null) { 1041 loge("Failed to get package version for: " + packageName); 1042 return; 1043 } 1044 1045 logdWithLocalLog( 1046 "Save config to xml, packagename: " + packageName + " phoneId: " + phoneId); 1047 1048 FileOutputStream outFile = null; 1049 try { 1050 outFile = new FileOutputStream(new File(mContext.getFilesDir(), fileName)); 1051 config.putString(KEY_VERSION, version); 1052 config.writeToStream(outFile); 1053 outFile.flush(); 1054 outFile.close(); 1055 } catch (IOException e) { 1056 loge(e.toString()); 1057 } 1058 } 1059 1060 @VisibleForTesting saveConfigToXml(@ullable String packageName, @NonNull String extraString, int phoneId, @NonNull CarrierIdentifier carrierId, @NonNull PersistableBundle config)1061 /* package */ void saveConfigToXml(@Nullable String packageName, @NonNull String extraString, 1062 int phoneId, @NonNull CarrierIdentifier carrierId, @NonNull PersistableBundle config) { 1063 saveConfigToXml(packageName, extraString, phoneId, carrierId, config, false); 1064 } 1065 1066 @VisibleForTesting saveNoSimConfigToXml(@ullable String packageName, @NonNull PersistableBundle config)1067 /* package */ void saveNoSimConfigToXml(@Nullable String packageName, 1068 @NonNull PersistableBundle config) { 1069 saveConfigToXml(packageName, "", -1, null, config, true); 1070 } 1071 1072 /** 1073 * Reads a bundle from an XML file. 1074 * 1075 * This restores a bundle that was written with {@link #saveConfigToXml}. This returns the saved 1076 * config bundle for the given package and phone ID. 1077 * 1078 * In case of errors, or if the saved config is from a different package version than the 1079 * current version, then null will be returned. 1080 * 1081 * @param packageName the name of the package from which we fetched this bundle. 1082 * @param extraString An extra string to be used in the XML file name. 1083 * @param phoneId the phone ID. 1084 * @param isNoSimConfig whether this is invoked for noSimConfig or not. 1085 * @return the bundle from the XML file. Returns null if there is no saved config, the saved 1086 * version does not match, or reading config fails. 1087 */ 1088 @Nullable restoreConfigFromXml(@ullable String packageName, @NonNull String extraString, int phoneId, boolean isNoSimConfig)1089 private PersistableBundle restoreConfigFromXml(@Nullable String packageName, 1090 @NonNull String extraString, int phoneId, boolean isNoSimConfig) { 1091 if (packageName == null) { 1092 loge("Cannot restore config with null packageName"); 1093 } 1094 final String version = getPackageVersion(packageName); 1095 if (version == null) { 1096 loge("Failed to get package version for: " + packageName); 1097 return null; 1098 } 1099 1100 String fileName; 1101 String iccid = null; 1102 if (isNoSimConfig) { 1103 fileName = getFilenameForNoSimConfig(packageName); 1104 } else { 1105 if (TelephonyManager.getSimStateForSlotIndex(phoneId) 1106 != TelephonyManager.SIM_STATE_LOADED) { 1107 loge("Skip restore config because SIM records are not loaded."); 1108 return null; 1109 } 1110 1111 iccid = getIccIdForPhoneId(phoneId); 1112 final int cid = getSpecificCarrierIdForPhoneId(phoneId); 1113 if (iccid == null) { 1114 loge("Cannot restore config with null iccid."); 1115 return null; 1116 } 1117 fileName = getFilenameForConfig(packageName, extraString, iccid, cid); 1118 } 1119 1120 PersistableBundle restoredBundle = null; 1121 File file = null; 1122 FileInputStream inFile = null; 1123 try { 1124 file = new File(mContext.getFilesDir(),fileName); 1125 inFile = new FileInputStream(file); 1126 1127 restoredBundle = PersistableBundle.readFromStream(inFile); 1128 String savedVersion = restoredBundle.getString(KEY_VERSION); 1129 restoredBundle.remove(KEY_VERSION); 1130 1131 if (!version.equals(savedVersion)) { 1132 loge("Saved version mismatch: " + version + " vs " + savedVersion); 1133 restoredBundle = null; 1134 } 1135 1136 inFile.close(); 1137 } catch (FileNotFoundException e) { 1138 // Missing file is normal occurrence that might occur with a new sim or when restoring 1139 // an override file during boot and should not be treated as an error. 1140 if (file != null) { 1141 if (isNoSimConfig) { 1142 logd("File not found: " + file.getPath()); 1143 } else { 1144 String filePath = file.getPath(); 1145 filePath = getFilePathForLogging(filePath, iccid); 1146 logd("File not found : " + filePath); 1147 } 1148 } 1149 } catch (IOException e) { 1150 loge(e.toString()); 1151 } 1152 1153 return restoredBundle; 1154 } 1155 1156 /** 1157 * This method will mask most part of iccid in the filepath for logging on userbuild 1158 */ 1159 @NonNull getFilePathForLogging(@ullable String filePath, @Nullable String iccid)1160 private String getFilePathForLogging(@Nullable String filePath, @Nullable String iccid) { 1161 // If loggable then return with actual file path 1162 if (Rlog.isLoggable(LOG_TAG, Log.VERBOSE)) { 1163 return filePath; 1164 } 1165 String path = filePath; 1166 int length = (iccid != null) ? iccid.length() : 0; 1167 if (length > 5 && filePath != null) { 1168 path = filePath.replace(iccid.substring(5), "***************"); 1169 } 1170 return path; 1171 } 1172 1173 @Nullable restoreConfigFromXml(@ullable String packageName, @NonNull String extraString, int phoneId)1174 private PersistableBundle restoreConfigFromXml(@Nullable String packageName, 1175 @NonNull String extraString, int phoneId) { 1176 return restoreConfigFromXml(packageName, extraString, phoneId, false); 1177 } 1178 1179 @Nullable restoreNoSimConfigFromXml(@ullable String packageName)1180 private PersistableBundle restoreNoSimConfigFromXml(@Nullable String packageName) { 1181 return restoreConfigFromXml(packageName, "", -1, true); 1182 } 1183 1184 /** 1185 * Clears cached carrier config. 1186 * This deletes all saved XML files associated with the given package name. If packageName is 1187 * null, then it deletes all saved XML files. 1188 * 1189 * @param packageName the name of a carrier package, or null if all cached config should be 1190 * cleared. 1191 * @return true iff one or more files were deleted. 1192 */ clearCachedConfigForPackage(@ullable final String packageName)1193 private boolean clearCachedConfigForPackage(@Nullable final String packageName) { 1194 File dir = mContext.getFilesDir(); 1195 File[] packageFiles = dir.listFiles(new FilenameFilter() { 1196 public boolean accept(File dir, String filename) { 1197 if (packageName != null) { 1198 return filename.startsWith("carrierconfig-" + packageName + "-"); 1199 } else { 1200 return filename.startsWith("carrierconfig-"); 1201 } 1202 } 1203 }); 1204 if (packageFiles == null || packageFiles.length < 1) return false; 1205 for (File f : packageFiles) { 1206 logd("Deleting " + getFilePathForLogging(f.getName())); 1207 f.delete(); 1208 } 1209 return true; 1210 } 1211 getFilePathForLogging(String filePath)1212 private String getFilePathForLogging(String filePath) { 1213 if (!TextUtils.isEmpty(filePath)) { 1214 String[] fileTokens = filePath.split("-"); 1215 if (fileTokens != null && fileTokens.length > 2) { 1216 String iccid = fileTokens[fileTokens.length -2]; 1217 return getFilePathForLogging(filePath, iccid); 1218 } 1219 return filePath; 1220 } 1221 return filePath; 1222 } 1223 1224 /** Builds a canonical file name for a config file. */ 1225 @NonNull getFilenameForConfig( @onNull String packageName, @NonNull String extraString, @NonNull String iccid, int cid)1226 private static String getFilenameForConfig( 1227 @NonNull String packageName, @NonNull String extraString, 1228 @NonNull String iccid, int cid) { 1229 // the same carrier should have a single copy of XML file named after carrier id. 1230 // However, it's still possible that platform doesn't recognize the current sim carrier, 1231 // we will use iccid + carrierid as the canonical file name. carrierid can also handle the 1232 // cases SIM OTA resolves to different carrier while iccid remains the same. 1233 return "carrierconfig-" + packageName + extraString + "-" + iccid + "-" + cid + ".xml"; 1234 } 1235 1236 /** Builds a canonical file name for no SIM config file. */ 1237 @NonNull getFilenameForNoSimConfig(@onNull String packageName)1238 private String getFilenameForNoSimConfig(@NonNull String packageName) { 1239 return "carrierconfig-" + packageName + "-" + "nosim" + ".xml"; 1240 } 1241 1242 /** Return the current version code of a package, or null if the name is not found. */ 1243 @Nullable getPackageVersion(@onNull String packageName)1244 private String getPackageVersion(@NonNull String packageName) { 1245 try { 1246 PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0); 1247 return Long.toString(info.getLongVersionCode()); 1248 } catch (PackageManager.NameNotFoundException e) { 1249 return null; 1250 } 1251 } 1252 1253 /** 1254 * Read up to date config. 1255 * 1256 * This reads config bundles for the given phoneId. That means getting the latest bundle from 1257 * the default app and a privileged carrier app, if present. This will not bind to an app if we 1258 * have a saved config file to use instead. 1259 */ updateConfigForPhoneId(int phoneId)1260 private void updateConfigForPhoneId(int phoneId) { 1261 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DO_FETCH_DEFAULT, phoneId, -1)); 1262 } 1263 onMultiSimConfigChanged()1264 private void onMultiSimConfigChanged() { 1265 int oldNumPhones = mNumPhones; 1266 mNumPhones = TelephonyManager.from(mContext).getActiveModemCount(); 1267 if (mNumPhones == oldNumPhones) { 1268 return; 1269 } 1270 logdWithLocalLog("mNumPhones change from " + oldNumPhones + " to " + mNumPhones); 1271 1272 // If DS -> SS switch, release the resources BEFORE truncating the arrays to avoid leaking 1273 for (int phoneId = mNumPhones; phoneId < oldNumPhones; phoneId++) { 1274 if (mServiceConnection[phoneId] != null) { 1275 unbindIfBound(mContext, mServiceConnection[phoneId], phoneId); 1276 } 1277 if (mServiceConnectionForNoSimConfig[phoneId] != null) { 1278 unbindIfBoundForNoSimConfig(mContext, mServiceConnectionForNoSimConfig[phoneId], 1279 phoneId); 1280 } 1281 } 1282 1283 // The phone to slot mapping may change, unregister here and re-register callbacks later 1284 for (int phoneId = 0; phoneId < oldNumPhones; phoneId++) { 1285 if (mCarrierServiceChangeCallbacks[phoneId] != null) { 1286 TelephonyManager.from(mContext).unregisterCarrierPrivilegesCallback( 1287 mCarrierServiceChangeCallbacks[phoneId]); 1288 } 1289 } 1290 1291 // Copy the original arrays, truncate or padding with zeros (if necessary) to new length 1292 mConfigFromDefaultApp = Arrays.copyOf(mConfigFromDefaultApp, mNumPhones); 1293 mConfigFromCarrierApp = Arrays.copyOf(mConfigFromCarrierApp, mNumPhones); 1294 mPersistentOverrideConfigs = Arrays.copyOf(mPersistentOverrideConfigs, mNumPhones); 1295 mOverrideConfigs = Arrays.copyOf(mOverrideConfigs, mNumPhones); 1296 mServiceConnection = Arrays.copyOf(mServiceConnection, mNumPhones); 1297 mServiceConnectionForNoSimConfig = 1298 Arrays.copyOf(mServiceConnectionForNoSimConfig, mNumPhones); 1299 mServiceBound = Arrays.copyOf(mServiceBound, mNumPhones); 1300 mServiceBoundForNoSimConfig = Arrays.copyOf(mServiceBoundForNoSimConfig, mNumPhones); 1301 mHasSentConfigChange = Arrays.copyOf(mHasSentConfigChange, mNumPhones); 1302 mFromSystemUnlocked = Arrays.copyOf(mFromSystemUnlocked, mNumPhones); 1303 mCarrierServiceChangeCallbacks = Arrays.copyOf(mCarrierServiceChangeCallbacks, mNumPhones); 1304 1305 // Load the config for all the phones and re-register callback AFTER padding the arrays. 1306 for (int phoneId = 0; phoneId < mNumPhones; phoneId++) { 1307 updateConfigForPhoneId(phoneId); 1308 mCarrierServiceChangeCallbacks[phoneId] = new CarrierServiceChangeCallback(phoneId); 1309 TelephonyManager.from(mContext).registerCarrierPrivilegesCallback(phoneId, 1310 new HandlerExecutor(mHandler), mCarrierServiceChangeCallbacks[phoneId]); 1311 } 1312 } 1313 1314 @Override 1315 @NonNull getConfigForSubId(int subscriptionId, @NonNull String callingPackage)1316 public PersistableBundle getConfigForSubId(int subscriptionId, @NonNull String callingPackage) { 1317 return getConfigForSubIdWithFeature(subscriptionId, callingPackage, null); 1318 } 1319 1320 @Override 1321 @NonNull getConfigForSubIdWithFeature(int subscriptionId, @NonNull String callingPackage, @Nullable String callingFeatureId)1322 public PersistableBundle getConfigForSubIdWithFeature(int subscriptionId, 1323 @NonNull String callingPackage, @Nullable String callingFeatureId) { 1324 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subscriptionId, 1325 callingPackage, callingFeatureId, "getCarrierConfig")) { 1326 return new PersistableBundle(); 1327 } 1328 1329 int phoneId = SubscriptionManager.getPhoneId(subscriptionId); 1330 PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig(); 1331 if (SubscriptionManager.isValidPhoneId(phoneId)) { 1332 PersistableBundle config = mConfigFromDefaultApp[phoneId]; 1333 if (config != null) { 1334 retConfig.putAll(config); 1335 } 1336 config = mConfigFromCarrierApp[phoneId]; 1337 if (config != null) { 1338 retConfig.putAll(config); 1339 } 1340 config = mPersistentOverrideConfigs[phoneId]; 1341 if (config != null) { 1342 retConfig.putAll(config); 1343 } 1344 config = mOverrideConfigs[phoneId]; 1345 if (config != null) { 1346 retConfig.putAll(config); 1347 } 1348 // Ignore the theoretical case of the default app not being present since that won't 1349 // work in CarrierConfigLoader today. 1350 final boolean allConfigsApplied = 1351 (mConfigFromCarrierApp[phoneId] != null 1352 || getCarrierPackageForPhoneId(phoneId) == null) 1353 && mConfigFromDefaultApp[phoneId] != null; 1354 retConfig.putBoolean( 1355 CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, allConfigsApplied); 1356 } else { 1357 if (mNoSimConfig != null) { 1358 retConfig.putAll(mNoSimConfig); 1359 } 1360 } 1361 return retConfig; 1362 } 1363 1364 @Override 1365 @NonNull getConfigSubsetForSubIdWithFeature(int subscriptionId, @NonNull String callingPackage, @Nullable String callingFeatureId, @NonNull String[] keys)1366 public PersistableBundle getConfigSubsetForSubIdWithFeature(int subscriptionId, 1367 @NonNull String callingPackage, @Nullable String callingFeatureId, 1368 @NonNull String[] keys) { 1369 Objects.requireNonNull(callingPackage, "Calling package must be non-null"); 1370 Objects.requireNonNull(keys, "Config keys must be non-null"); 1371 enforceCallerIsSystemOrRequestingPackage(callingPackage); 1372 1373 // Permission check is performed inside and an empty bundle will return on failure. 1374 // No SecurityException thrown here since most clients expect to retrieve the overridden 1375 // value if present or use default one if not 1376 PersistableBundle allConfigs = getConfigForSubIdWithFeature(subscriptionId, callingPackage, 1377 callingFeatureId); 1378 if (allConfigs.isEmpty()) { 1379 return allConfigs; 1380 } 1381 for (String key : keys) { 1382 Objects.requireNonNull(key, "Config key must be non-null"); 1383 } 1384 1385 PersistableBundle configSubset = new PersistableBundle( 1386 keys.length + CONFIG_SUBSET_METADATA_KEYS.length); 1387 for (String carrierConfigKey : keys) { 1388 Object value = allConfigs.get(carrierConfigKey); 1389 if (value == null) { 1390 // Filter out keys without values. 1391 // In history, many AOSP or OEMs/carriers private configs didn't provide default 1392 // values. We have to continue supporting them for now. See b/261776046 for details. 1393 continue; 1394 } 1395 // Config value itself could be PersistableBundle which requires different API to put 1396 if (value instanceof PersistableBundle) { 1397 configSubset.putPersistableBundle(carrierConfigKey, (PersistableBundle) value); 1398 } else { 1399 configSubset.putObject(carrierConfigKey, value); 1400 } 1401 } 1402 1403 // Configs in CONFIG_SUBSET_ALWAYS_INCLUDED_KEYS should always be included 1404 for (String generalKey : CONFIG_SUBSET_METADATA_KEYS) { 1405 configSubset.putObject(generalKey, allConfigs.get(generalKey)); 1406 } 1407 1408 return configSubset; 1409 } 1410 1411 @Override overrideConfig(int subscriptionId, @Nullable PersistableBundle overrides, boolean persistent)1412 public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrides, 1413 boolean persistent) { 1414 mContext.enforceCallingOrSelfPermission( 1415 android.Manifest.permission.MODIFY_PHONE_STATE, null); 1416 int phoneId = SubscriptionManager.getPhoneId(subscriptionId); 1417 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1418 logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId); 1419 throw new IllegalArgumentException( 1420 "Invalid phoneId " + phoneId + " for subId " + subscriptionId); 1421 } 1422 // Post to run on handler thread on which all states should be confined. 1423 mHandler.post(() -> { 1424 overrideConfig(mOverrideConfigs, phoneId, overrides); 1425 1426 if (persistent) { 1427 overrideConfig(mPersistentOverrideConfigs, phoneId, overrides); 1428 1429 if (overrides != null) { 1430 final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId); 1431 saveConfigToXml(mPlatformCarrierConfigPackage, OVERRIDE_PACKAGE_ADDITION, 1432 phoneId, 1433 carrierId, mPersistentOverrideConfigs[phoneId]); 1434 } else { 1435 final String iccid = getIccIdForPhoneId(phoneId); 1436 final int cid = getSpecificCarrierIdForPhoneId(phoneId); 1437 String fileName = getFilenameForConfig(mPlatformCarrierConfigPackage, 1438 OVERRIDE_PACKAGE_ADDITION, iccid, cid); 1439 File fileToDelete = new File(mContext.getFilesDir(), fileName); 1440 fileToDelete.delete(); 1441 } 1442 } 1443 updateSubscriptionDatabase(phoneId); 1444 }); 1445 } 1446 overrideConfig(@onNull PersistableBundle[] currentOverrides, int phoneId, @Nullable PersistableBundle overrides)1447 private void overrideConfig(@NonNull PersistableBundle[] currentOverrides, int phoneId, 1448 @Nullable PersistableBundle overrides) { 1449 if (overrides == null) { 1450 currentOverrides[phoneId] = new PersistableBundle(); 1451 } else if (currentOverrides[phoneId] == null) { 1452 currentOverrides[phoneId] = overrides; 1453 } else { 1454 currentOverrides[phoneId].putAll(overrides); 1455 } 1456 } 1457 1458 @Override notifyConfigChangedForSubId(int subscriptionId)1459 public void notifyConfigChangedForSubId(int subscriptionId) { 1460 // Requires the calling app to be either a carrier privileged app for this subId or 1461 // system privileged app with MODIFY_PHONE_STATE permission. 1462 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mContext, 1463 subscriptionId, "Require carrier privileges or MODIFY_PHONE_STATE permission."); 1464 1465 int phoneId = SubscriptionManager.getPhoneId(subscriptionId); 1466 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1467 logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId); 1468 throw new IllegalArgumentException( 1469 "Invalid phoneId " + phoneId + " for subId " + subscriptionId); 1470 } 1471 1472 // This method should block until deleting has completed, so that an error which prevents us 1473 // from clearing the cache is passed back to the carrier app. With the files successfully 1474 // deleted, this can return and we will eventually bind to the carrier app. 1475 String callingPackageName = mContext.getPackageManager().getNameForUid( 1476 Binder.getCallingUid()); 1477 clearCachedConfigForPackage(callingPackageName); 1478 updateConfigForPhoneId(phoneId); 1479 } 1480 1481 @Override updateConfigForPhoneId(int phoneId, @NonNull String simState)1482 public void updateConfigForPhoneId(int phoneId, @NonNull String simState) { 1483 mContext.enforceCallingOrSelfPermission( 1484 android.Manifest.permission.MODIFY_PHONE_STATE, null); 1485 logdWithLocalLog("Update config for phoneId: " + phoneId + " simState: " + simState); 1486 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1487 throw new IllegalArgumentException("Invalid phoneId: " + phoneId); 1488 } 1489 // requires Java 7 for switch on string. 1490 switch (simState) { 1491 case IccCardConstants.INTENT_VALUE_ICC_ABSENT: 1492 case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR: 1493 case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED: 1494 case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN: 1495 case IccCardConstants.INTENT_VALUE_ICC_NOT_READY: 1496 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_CONFIG, phoneId, -1)); 1497 break; 1498 case IccCardConstants.INTENT_VALUE_ICC_LOADED: 1499 case IccCardConstants.INTENT_VALUE_ICC_LOCKED: 1500 updateConfigForPhoneId(phoneId); 1501 break; 1502 } 1503 } 1504 1505 @Override 1506 @NonNull getDefaultCarrierServicePackageName()1507 public String getDefaultCarrierServicePackageName() { 1508 mContext.enforceCallingOrSelfPermission( 1509 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1510 "getDefaultCarrierServicePackageName"); 1511 return mPlatformCarrierConfigPackage; 1512 } 1513 1514 @VisibleForTesting 1515 @NonNull getHandler()1516 /* package */ Handler getHandler() { 1517 return mHandler; 1518 } 1519 1520 @VisibleForTesting 1521 @Nullable getConfigFromDefaultApp(int phoneId)1522 /* package */ PersistableBundle getConfigFromDefaultApp(int phoneId) { 1523 return mConfigFromDefaultApp[phoneId]; 1524 } 1525 1526 @VisibleForTesting 1527 @Nullable getConfigFromCarrierApp(int phoneId)1528 /* package */ PersistableBundle getConfigFromCarrierApp(int phoneId) { 1529 return mConfigFromCarrierApp[phoneId]; 1530 } 1531 1532 @VisibleForTesting 1533 @NonNull getNoSimConfig()1534 /* package */ PersistableBundle getNoSimConfig() { 1535 return mNoSimConfig; 1536 } 1537 1538 @VisibleForTesting 1539 @Nullable getOverrideConfig(int phoneId)1540 /* package */ PersistableBundle getOverrideConfig(int phoneId) { 1541 return mOverrideConfigs[phoneId]; 1542 } 1543 1544 // TODO(b/185129900): always call unbindService after bind, no matter if it succeeded unbindIfBound(@onNull Context context, @NonNull CarrierServiceConnection conn, int phoneId)1545 private void unbindIfBound(@NonNull Context context, @NonNull CarrierServiceConnection conn, 1546 int phoneId) { 1547 if (mServiceBound[phoneId]) { 1548 mServiceBound[phoneId] = false; 1549 context.unbindService(conn); 1550 } 1551 } 1552 unbindIfBoundForNoSimConfig(@onNull Context context, @NonNull CarrierServiceConnection conn, int phoneId)1553 private void unbindIfBoundForNoSimConfig(@NonNull Context context, 1554 @NonNull CarrierServiceConnection conn, int phoneId) { 1555 if (mServiceBoundForNoSimConfig[phoneId]) { 1556 mServiceBoundForNoSimConfig[phoneId] = false; 1557 context.unbindService(conn); 1558 } 1559 } 1560 1561 /** 1562 * Returns a boxed Integer object for phoneId, services as message token to distinguish messages 1563 * with same code when calling {@link Handler#removeMessages(int, Object)}. 1564 */ 1565 @NonNull getMessageToken(int phoneId)1566 private Integer getMessageToken(int phoneId) { 1567 if (phoneId < -128 || phoneId > 127) { 1568 throw new IllegalArgumentException("phoneId should be in range [-128, 127], inclusive"); 1569 } 1570 // Integer#valueOf guarantees the integers within [-128, 127] are cached and thus memory 1571 // comparison (==) returns true for the same integer. 1572 return Integer.valueOf(phoneId); 1573 } 1574 1575 /** 1576 * If {@code args} contains {@link #DUMP_ARG_REQUESTING_PACKAGE} and a following package name, 1577 * we'll also call {@link IBinder#dump} on the default carrier service (if bound) and the 1578 * specified carrier service (if bound). Typically, this is done for connectivity bug reports 1579 * where we don't call {@code dumpsys activity service all-non-platform} because that contains 1580 * too much info, but we still want to let carrier apps include their diagnostics. 1581 */ 1582 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args)1583 public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { 1584 IndentingPrintWriter indentPW = new IndentingPrintWriter(pw, " "); 1585 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1586 != PackageManager.PERMISSION_GRANTED) { 1587 indentPW.println("Permission Denial: can't dump carrierconfig from from pid=" 1588 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1589 return; 1590 } 1591 String requestingPackage = null; 1592 int requestingPackageIndex = ArrayUtils.indexOf(args, DUMP_ARG_REQUESTING_PACKAGE); 1593 if (requestingPackageIndex >= 0 && requestingPackageIndex < args.length - 1 1594 && !TextUtils.isEmpty(args[requestingPackageIndex + 1])) { 1595 requestingPackage = args[requestingPackageIndex + 1]; 1596 // Throws a SecurityException if the caller is impersonating another app in an effort to 1597 // dump extra info (which may contain PII the caller doesn't have a right to). 1598 enforceCallerIsSystemOrRequestingPackage(requestingPackage); 1599 } 1600 1601 indentPW.println("CarrierConfigLoader: " + this); 1602 for (int i = 0; i < mNumPhones; i++) { 1603 indentPW.println("Phone Id = " + i); 1604 // display default values in CarrierConfigManager 1605 printConfig(CarrierConfigManager.getDefaultConfig(), indentPW, 1606 "Default Values from CarrierConfigManager"); 1607 // display ConfigFromDefaultApp 1608 printConfig(mConfigFromDefaultApp[i], indentPW, "mConfigFromDefaultApp"); 1609 // display ConfigFromCarrierApp 1610 printConfig(mConfigFromCarrierApp[i], indentPW, "mConfigFromCarrierApp"); 1611 printConfig(mPersistentOverrideConfigs[i], indentPW, "mPersistentOverrideConfigs"); 1612 printConfig(mOverrideConfigs[i], indentPW, "mOverrideConfigs"); 1613 } 1614 1615 printConfig(mNoSimConfig, indentPW, "mNoSimConfig"); 1616 indentPW.println("CarrierConfigLoadingLog="); 1617 mCarrierConfigLoadingLog.dump(fd, indentPW, args); 1618 1619 if (requestingPackage != null) { 1620 logd("Including default and requesting package " + requestingPackage 1621 + " carrier services in dump"); 1622 indentPW.println(""); 1623 indentPW.println("Connected services"); 1624 dumpCarrierServiceIfBound(fd, indentPW, "Default config package", 1625 mPlatformCarrierConfigPackage, false /* considerCarrierPrivileges */); 1626 dumpCarrierServiceIfBound(fd, indentPW, "Requesting package", requestingPackage, 1627 true /* considerCarrierPrivileges */); 1628 } 1629 } 1630 printConfig(@onNull PersistableBundle configApp, @NonNull IndentingPrintWriter indentPW, @NonNull String name)1631 private void printConfig(@NonNull PersistableBundle configApp, 1632 @NonNull IndentingPrintWriter indentPW, @NonNull String name) { 1633 indentPW.increaseIndent(); 1634 if (configApp == null) { 1635 indentPW.println(name + " : null "); 1636 indentPW.decreaseIndent(); 1637 indentPW.println(""); 1638 return; 1639 } 1640 indentPW.println(name + " : "); 1641 List<String> sortedKeys = new ArrayList<String>(configApp.keySet()); 1642 Collections.sort(sortedKeys); 1643 indentPW.increaseIndent(); 1644 indentPW.increaseIndent(); 1645 for (String key : sortedKeys) { 1646 if (configApp.get(key) != null && configApp.get(key) instanceof Object[]) { 1647 indentPW.println(key + " = " + 1648 Arrays.toString((Object[]) configApp.get(key))); 1649 } else if (configApp.get(key) != null && configApp.get(key) instanceof int[]) { 1650 indentPW.println(key + " = " + Arrays.toString((int[]) configApp.get(key))); 1651 } else { 1652 indentPW.println(key + " = " + configApp.get(key)); 1653 } 1654 } 1655 indentPW.decreaseIndent(); 1656 indentPW.decreaseIndent(); 1657 indentPW.decreaseIndent(); 1658 indentPW.println(""); 1659 } 1660 1661 /** 1662 * Passes without problem when one of these conditions is true: 1663 * - The caller is a privileged UID (e.g. for dumpstate.cpp generating a bug report, where the 1664 * system knows the true caller plumbed in through the {@link android.os.BugreportManager} API). 1665 * - The caller's UID matches the supplied package. 1666 * 1667 * @throws SecurityException if none of the above conditions are met. 1668 */ enforceCallerIsSystemOrRequestingPackage(@onNull String requestingPackage)1669 private void enforceCallerIsSystemOrRequestingPackage(@NonNull String requestingPackage) 1670 throws SecurityException { 1671 final int callingUid = Binder.getCallingUid(); 1672 if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID 1673 || callingUid == Process.SHELL_UID || callingUid == Process.PHONE_UID) { 1674 // Bug reports (dumpstate.cpp) run as SHELL, and let some other privileged UIDs through 1675 // as well. 1676 return; 1677 } 1678 // An app is trying to dump extra detail, block it if they aren't who they claim to be. 1679 AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 1680 if (appOps == null) { 1681 throw new SecurityException("No AppOps"); 1682 } 1683 // Will throw a SecurityException if the UID and package don't match. 1684 appOps.checkPackage(callingUid, requestingPackage); 1685 } 1686 1687 /** 1688 * Searches for one or more appropriate {@link CarrierService} instances to dump based on the 1689 * current connections. 1690 * 1691 * @param targetPkgName the target package name to dump carrier services for 1692 * @param considerCarrierPrivileges if true, allow a carrier service to be dumped if it shares 1693 * carrier privileges with {@code targetPkgName}; 1694 * otherwise, only dump a carrier service if it is {@code 1695 * targetPkgName} 1696 */ dumpCarrierServiceIfBound(@onNull FileDescriptor fd, @NonNull IndentingPrintWriter indentPW, @NonNull String prefix, @NonNull String targetPkgName, boolean considerCarrierPrivileges)1697 private void dumpCarrierServiceIfBound(@NonNull FileDescriptor fd, 1698 @NonNull IndentingPrintWriter indentPW, @NonNull String prefix, 1699 @NonNull String targetPkgName, boolean considerCarrierPrivileges) { 1700 // Null package is possible if it's early in the boot process, there was a recent crash, we 1701 // loaded the config from XML most recently, or a SIM slot is empty. Carrier apps with 1702 // long-lived bindings should typically get dumped here regardless. Even if an app is being 1703 // used for multiple phoneIds, we assume that it's smart enough to handle that on its own, 1704 // and that in most cases we'd just be dumping duplicate information and bloating a report. 1705 indentPW.increaseIndent(); 1706 indentPW.println(prefix + " : " + targetPkgName); 1707 Set<String> dumpedPkgNames = new ArraySet<>(mServiceConnection.length); 1708 for (CarrierServiceConnection connection : mServiceConnection) { 1709 if (connection == null || !SubscriptionManager.isValidPhoneId(connection.phoneId) 1710 || TextUtils.isEmpty(connection.pkgName)) { 1711 continue; 1712 } 1713 final String servicePkgName = connection.pkgName; 1714 // Note: we intentionally ignore system components here because we should NOT match the 1715 // shell caller that's typically used for bug reports via non-BugreportManager triggers. 1716 final boolean exactPackageMatch = TextUtils.equals(targetPkgName, servicePkgName); 1717 final boolean carrierPrivilegesMatch = 1718 considerCarrierPrivileges && hasCarrierPrivileges(targetPkgName, 1719 connection.phoneId); 1720 if (!exactPackageMatch && !carrierPrivilegesMatch) continue; 1721 // Make sure this service is actually alive before trying to dump it. We don't pay 1722 // attention to mServiceBound[connection.phoneId] because typically carrier apps will 1723 // request long-lived bindings, and even if we unbind the app, it may still be alive due 1724 // to CarrierServiceBindHelper. Pull it out as a reference so even if it gets set to 1725 // null within the ServiceConnection during unbinding we can avoid an NPE. 1726 final IBinder service = connection.service; 1727 if (service == null || !service.isBinderAlive() || !service.pingBinder()) continue; 1728 // We've got a live service. Last check is just to make sure we don't dump a package 1729 // multiple times. 1730 if (!dumpedPkgNames.add(servicePkgName)) continue; 1731 if (!exactPackageMatch) { 1732 logd(targetPkgName + " has carrier privileges on phoneId " + connection.phoneId 1733 + ", service provided by " + servicePkgName); 1734 indentPW.increaseIndent(); 1735 indentPW.println("Proxy : " + servicePkgName); 1736 indentPW.decreaseIndent(); 1737 } 1738 // Flush before we let the app output anything to ensure correct ordering of output. 1739 // Internally, Binder#dump calls flush on its printer after finishing so we don't 1740 // need to do anything after. 1741 indentPW.flush(); 1742 try { 1743 logd("Dumping " + servicePkgName); 1744 // We don't need to give the carrier service any args. 1745 connection.service.dump(fd, null /* args */); 1746 logd("Done with " + servicePkgName); 1747 } catch (RemoteException e) { 1748 logd("RemoteException from " + servicePkgName, e); 1749 indentPW.increaseIndent(); 1750 indentPW.println("RemoteException"); 1751 indentPW.increaseIndent(); 1752 e.printStackTrace(indentPW); 1753 indentPW.decreaseIndent(); 1754 indentPW.decreaseIndent(); 1755 // We won't retry this package again because now it's in dumpedPkgNames. 1756 } 1757 indentPW.println(""); 1758 } 1759 if (dumpedPkgNames.isEmpty()) { 1760 indentPW.increaseIndent(); 1761 indentPW.println("Not bound"); 1762 indentPW.decreaseIndent(); 1763 indentPW.println(""); 1764 } 1765 indentPW.decreaseIndent(); 1766 } 1767 hasCarrierPrivileges(@onNull String pkgName, int phoneId)1768 private boolean hasCarrierPrivileges(@NonNull String pkgName, int phoneId) { 1769 int subId = SubscriptionManager.getSubscriptionId(phoneId); 1770 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 1771 return false; 1772 } 1773 return TelephonyManager.from(mContext).createForSubscriptionId(subId) 1774 .checkCarrierPrivilegesForPackage(pkgName) 1775 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 1776 } 1777 1778 private class CarrierServiceConnection implements ServiceConnection { 1779 final int phoneId; 1780 @NonNull final String pkgName; 1781 final int eventId; 1782 IBinder service; 1783 CarrierServiceConnection(int phoneId, @NonNull String pkgName, int eventId)1784 CarrierServiceConnection(int phoneId, @NonNull String pkgName, int eventId) { 1785 this.phoneId = phoneId; 1786 this.pkgName = pkgName; 1787 this.eventId = eventId; 1788 } 1789 1790 @Override onServiceConnected(@onNull ComponentName name, @NonNull IBinder service)1791 public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) { 1792 logd("Connected to config app: " + name.flattenToShortString()); 1793 this.service = service; 1794 mHandler.sendMessage(mHandler.obtainMessage(eventId, phoneId, -1, this)); 1795 } 1796 1797 @Override onServiceDisconnected(@onNull ComponentName name)1798 public void onServiceDisconnected(@NonNull ComponentName name) { 1799 logd("Disconnected from config app: " + name.flattenToShortString()); 1800 this.service = null; 1801 } 1802 1803 @Override onBindingDied(@onNull ComponentName name)1804 public void onBindingDied(@NonNull ComponentName name) { 1805 logd("Binding died from config app: " + name.flattenToShortString()); 1806 this.service = null; 1807 } 1808 1809 @Override onNullBinding(@onNull ComponentName name)1810 public void onNullBinding(@NonNull ComponentName name) { 1811 logd("Null binding from config app: " + name.flattenToShortString()); 1812 this.service = null; 1813 } 1814 } 1815 1816 private class ConfigLoaderBroadcastReceiver extends BroadcastReceiver { 1817 @Override onReceive(@onNull Context context, @NonNull Intent intent)1818 public void onReceive(@NonNull Context context, @NonNull Intent intent) { 1819 switch (intent.getAction()) { 1820 case Intent.ACTION_BOOT_COMPLETED: 1821 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_UNLOCKED, null)); 1822 break; 1823 } 1824 } 1825 } 1826 1827 private class CarrierServiceChangeCallback implements 1828 TelephonyManager.CarrierPrivilegesCallback { 1829 final int mPhoneId; 1830 // CarrierPrivilegesCallback will be triggered upon registration. Filter the first callback 1831 // here since we really care of the *change* of carrier service instead of the content 1832 private boolean mHasSentServiceChangeCallback; 1833 CarrierServiceChangeCallback(int phoneId)1834 CarrierServiceChangeCallback(int phoneId) { 1835 this.mPhoneId = phoneId; 1836 this.mHasSentServiceChangeCallback = false; 1837 } 1838 1839 @Override onCarrierPrivilegesChanged( @ndroidx.annotation.NonNull Set<String> privilegedPackageNames, @androidx.annotation.NonNull Set<Integer> privilegedUids)1840 public void onCarrierPrivilegesChanged( 1841 @androidx.annotation.NonNull Set<String> privilegedPackageNames, 1842 @androidx.annotation.NonNull Set<Integer> privilegedUids) { 1843 // Ignored, not interested here 1844 } 1845 1846 @Override onCarrierServiceChanged( @ndroidx.annotation.Nullable String carrierServicePackageName, int carrierServiceUid)1847 public void onCarrierServiceChanged( 1848 @androidx.annotation.Nullable String carrierServicePackageName, 1849 int carrierServiceUid) { 1850 // Ignore the first callback which is triggered upon registration 1851 if (!mHasSentServiceChangeCallback) { 1852 mHasSentServiceChangeCallback = true; 1853 return; 1854 } 1855 mHandler.sendMessage( 1856 mHandler.obtainMessage(EVENT_PACKAGE_CHANGED, mPhoneId, -1, 1857 carrierServicePackageName)); 1858 } 1859 } 1860 1861 // Get readable string for the message code supported in this class. 1862 @NonNull eventToString(int code)1863 private static String eventToString(int code) { 1864 switch (code) { 1865 case EVENT_CLEAR_CONFIG: 1866 return "EVENT_CLEAR_CONFIG"; 1867 case EVENT_CONNECTED_TO_DEFAULT: 1868 return "EVENT_CONNECTED_TO_DEFAULT"; 1869 case EVENT_CONNECTED_TO_CARRIER: 1870 return "EVENT_CONNECTED_TO_CARRIER"; 1871 case EVENT_FETCH_DEFAULT_DONE: 1872 return "EVENT_FETCH_DEFAULT_DONE"; 1873 case EVENT_FETCH_CARRIER_DONE: 1874 return "EVENT_FETCH_CARRIER_DONE"; 1875 case EVENT_DO_FETCH_DEFAULT: 1876 return "EVENT_DO_FETCH_DEFAULT"; 1877 case EVENT_DO_FETCH_CARRIER: 1878 return "EVENT_DO_FETCH_CARRIER"; 1879 case EVENT_PACKAGE_CHANGED: 1880 return "EVENT_PACKAGE_CHANGED"; 1881 case EVENT_BIND_DEFAULT_TIMEOUT: 1882 return "EVENT_BIND_DEFAULT_TIMEOUT"; 1883 case EVENT_BIND_CARRIER_TIMEOUT: 1884 return "EVENT_BIND_CARRIER_TIMEOUT"; 1885 case EVENT_CHECK_SYSTEM_UPDATE: 1886 return "EVENT_CHECK_SYSTEM_UPDATE"; 1887 case EVENT_SYSTEM_UNLOCKED: 1888 return "EVENT_SYSTEM_UNLOCKED"; 1889 case EVENT_FETCH_DEFAULT_TIMEOUT: 1890 return "EVENT_FETCH_DEFAULT_TIMEOUT"; 1891 case EVENT_FETCH_CARRIER_TIMEOUT: 1892 return "EVENT_FETCH_CARRIER_TIMEOUT"; 1893 case EVENT_SUBSCRIPTION_INFO_UPDATED: 1894 return "EVENT_SUBSCRIPTION_INFO_UPDATED"; 1895 case EVENT_MULTI_SIM_CONFIG_CHANGED: 1896 return "EVENT_MULTI_SIM_CONFIG_CHANGED"; 1897 case EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG: 1898 return "EVENT_DO_FETCH_DEFAULT_FOR_NO_SIM_CONFIG"; 1899 case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE: 1900 return "EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_DONE"; 1901 case EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG: 1902 return "EVENT_CONNECTED_TO_DEFAULT_FOR_NO_SIM_CONFIG"; 1903 case EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT: 1904 return "EVENT_BIND_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT"; 1905 case EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT: 1906 return "EVENT_FETCH_DEFAULT_FOR_NO_SIM_CONFIG_TIMEOUT"; 1907 default: 1908 return "UNKNOWN(" + code + ")"; 1909 } 1910 } 1911 logd(@onNull String msg)1912 private void logd(@NonNull String msg) { 1913 Log.d(LOG_TAG, msg); 1914 } 1915 logd(@onNull String msg, Throwable tr)1916 private void logd(@NonNull String msg, Throwable tr) { 1917 Log.d(LOG_TAG, msg, tr); 1918 } 1919 logdWithLocalLog(@onNull String msg)1920 private void logdWithLocalLog(@NonNull String msg) { 1921 Log.d(LOG_TAG, msg); 1922 mCarrierConfigLoadingLog.log(msg); 1923 } 1924 loge(@onNull String msg)1925 private void loge(@NonNull String msg) { 1926 Log.e(LOG_TAG, msg); 1927 mCarrierConfigLoadingLog.log(msg); 1928 } 1929 } 1930