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