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