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.Message; 40 import android.os.PersistableBundle; 41 import android.os.Process; 42 import android.os.RemoteException; 43 import android.os.ResultReceiver; 44 import android.os.ServiceManager; 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.TelephonyManager; 53 import android.text.TextUtils; 54 import android.util.ArraySet; 55 import android.util.LocalLog; 56 import android.util.Log; 57 58 import com.android.internal.telephony.ICarrierConfigLoader; 59 import com.android.internal.telephony.IccCardConstants; 60 import com.android.internal.telephony.Phone; 61 import com.android.internal.telephony.PhoneFactory; 62 import com.android.internal.telephony.SubscriptionInfoUpdater; 63 import com.android.internal.telephony.TelephonyPermissions; 64 import com.android.internal.telephony.util.ArrayUtils; 65 import com.android.internal.util.IndentingPrintWriter; 66 67 import java.io.File; 68 import java.io.FileDescriptor; 69 import java.io.FileInputStream; 70 import java.io.FileNotFoundException; 71 import java.io.FileOutputStream; 72 import java.io.FilenameFilter; 73 import java.io.IOException; 74 import java.io.PrintWriter; 75 import java.util.ArrayList; 76 import java.util.Arrays; 77 import java.util.Collections; 78 import java.util.List; 79 import java.util.Set; 80 81 /** 82 * CarrierConfigLoader binds to privileged carrier apps to fetch carrier config overlays. 83 */ 84 public class CarrierConfigLoader extends ICarrierConfigLoader.Stub { 85 private static final String LOG_TAG = "CarrierConfigLoader"; 86 87 // Package name for platform carrier config app, bundled with system image. 88 private final String mPlatformCarrierConfigPackage; 89 90 /** The singleton instance. */ 91 private static CarrierConfigLoader sInstance; 92 // The context for phone app, passed from PhoneGlobals. 93 private Context mContext; 94 // Carrier configs from default app, indexed by phoneID. 95 private PersistableBundle[] mConfigFromDefaultApp; 96 // Carrier configs from privileged carrier config app, indexed by phoneID. 97 private PersistableBundle[] mConfigFromCarrierApp; 98 // Persistent Carrier configs that are provided via the override test API, indexed by phone ID. 99 private PersistableBundle[] mPersistentOverrideConfigs; 100 // Carrier configs that are provided via the override test API, indexed by phone ID. 101 private PersistableBundle[] mOverrideConfigs; 102 // Service connection for binding to config app. 103 private CarrierServiceConnection[] mServiceConnection; 104 // Whether we are bound to a service for each phone 105 private boolean[] mServiceBound; 106 // Whether we have sent config change broadcast for each phone id. 107 private boolean[] mHasSentConfigChange; 108 // Whether the broadcast was sent from EVENT_SYSTEM_UNLOCKED, to track rebroadcasts 109 private boolean[] mFromSystemUnlocked; 110 // SubscriptionInfoUpdater 111 private final SubscriptionInfoUpdater mSubscriptionInfoUpdater; 112 113 // Broadcast receiver for Boot intents, register intent filter in construtor. 114 private final BroadcastReceiver mBootReceiver = new ConfigLoaderBroadcastReceiver(); 115 // Broadcast receiver for SIM and pkg intents, register intent filter in constructor. 116 private final BroadcastReceiver mPackageReceiver = new ConfigLoaderBroadcastReceiver(); 117 private final LocalLog mCarrierConfigLoadingLog = new LocalLog(100); 118 119 120 // Message codes; see mHandler below. 121 // Request from SubscriptionInfoUpdater when SIM becomes absent or error. 122 private static final int EVENT_CLEAR_CONFIG = 0; 123 // Has connected to default app. 124 private static final int EVENT_CONNECTED_TO_DEFAULT = 3; 125 // Has connected to carrier app. 126 private static final int EVENT_CONNECTED_TO_CARRIER = 4; 127 // Config has been loaded from default app (or cache). 128 private static final int EVENT_FETCH_DEFAULT_DONE = 5; 129 // Config has been loaded from carrier app (or cache). 130 private static final int EVENT_FETCH_CARRIER_DONE = 6; 131 // Attempt to fetch from default app or read from XML. 132 private static final int EVENT_DO_FETCH_DEFAULT = 7; 133 // Attempt to fetch from carrier app or read from XML. 134 private static final int EVENT_DO_FETCH_CARRIER = 8; 135 // A package has been installed, uninstalled, or updated. 136 private static final int EVENT_PACKAGE_CHANGED = 9; 137 // Bind timed out for the default app. 138 private static final int EVENT_BIND_DEFAULT_TIMEOUT = 10; 139 // Bind timed out for a carrier app. 140 private static final int EVENT_BIND_CARRIER_TIMEOUT = 11; 141 // Check if the system fingerprint has changed. 142 private static final int EVENT_CHECK_SYSTEM_UPDATE = 12; 143 // Rerun carrier config binding after system is unlocked. 144 private static final int EVENT_SYSTEM_UNLOCKED = 13; 145 // Fetching config timed out from the default app. 146 private static final int EVENT_FETCH_DEFAULT_TIMEOUT = 14; 147 // Fetching config timed out from a carrier app. 148 private static final int EVENT_FETCH_CARRIER_TIMEOUT = 15; 149 // SubscriptionInfoUpdater has finished updating the sub for the carrier config. 150 private static final int EVENT_SUBSCRIPTION_INFO_UPDATED = 16; 151 // Multi-SIM config changed. 152 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 17; 153 154 private static final int BIND_TIMEOUT_MILLIS = 30000; 155 156 // Keys used for saving and restoring config bundle from file. 157 private static final String KEY_VERSION = "__carrier_config_package_version__"; 158 159 private static final String OVERRIDE_PACKAGE_ADDITION = "-override"; 160 161 // SharedPreferences key for last known build fingerprint. 162 private static final String KEY_FINGERPRINT = "build_fingerprint"; 163 164 // Argument for #dump that indicates we should also call the default and specified carrier 165 // service's #dump method. In multi-SIM devices, it's possible that carrier A is on SIM 1 and 166 // carrier B is on SIM 2, in which case we should not dump carrier B's service when carrier A 167 // requested the dump. 168 private static final String DUMP_ARG_REQUESTING_PACKAGE = "--requesting-package"; 169 170 // Handler to process various events. 171 // 172 // For each phoneId, the event sequence should be: 173 // fetch default, connected to default, fetch default (async), fetch default done, 174 // fetch carrier, connected to carrier, fetch carrier (async), fetch carrier done. 175 // 176 // If there is a saved config file for either the default app or the carrier app, we skip 177 // binding to the app and go straight from fetch to loaded. 178 // 179 // At any time, at most one connection is active. If events are not in this order, previous 180 // connection will be unbound, so only latest event takes effect. 181 // 182 // We broadcast ACTION_CARRIER_CONFIG_CHANGED after: 183 // 1. loading from carrier app (even if read from a file) 184 // 2. loading from default app if there is no carrier app (even if read from a file) 185 // 3. clearing config (e.g. due to sim removal) 186 // 4. encountering bind or IPC error 187 private class ConfigHandler extends Handler { 188 @Override handleMessage(Message msg)189 public void handleMessage(Message msg) { 190 final int phoneId = msg.arg1; 191 logdWithLocalLog("mHandler: " + msg.what + " phoneId: " + phoneId); 192 if (!SubscriptionManager.isValidPhoneId(phoneId) 193 && msg.what != EVENT_MULTI_SIM_CONFIG_CHANGED) { 194 return; 195 } 196 switch (msg.what) { 197 case EVENT_CLEAR_CONFIG: { 198 clearConfigForPhone(phoneId, true); 199 break; 200 } 201 202 case EVENT_SYSTEM_UNLOCKED: { 203 for (int i = 0; i < TelephonyManager.from(mContext).getActiveModemCount(); 204 ++i) { 205 // When the user unlocks the device, send the broadcast again (with a 206 // rebroadcast extra) if we have sent it before unlock. This will avoid 207 // trying to load the carrier config when the SIM is still loading when the 208 // unlock happens. 209 if (mHasSentConfigChange[i]) { 210 logdWithLocalLog("System unlocked"); 211 mFromSystemUnlocked[i] = true; 212 updateConfigForPhoneId(i); 213 } 214 } 215 break; 216 } 217 218 case EVENT_PACKAGE_CHANGED: { 219 final String carrierPackageName = (String) msg.obj; 220 // Only update if there are cached config removed to avoid updating config for 221 // unrelated packages. 222 if (clearCachedConfigForPackage(carrierPackageName)) { 223 int numPhones = TelephonyManager.from(mContext).getActiveModemCount(); 224 for (int i = 0; i < numPhones; ++i) { 225 logdWithLocalLog("Package changed: " + carrierPackageName 226 + ", phone=" + i); 227 updateConfigForPhoneId(i); 228 } 229 } 230 break; 231 } 232 233 case EVENT_DO_FETCH_DEFAULT: { 234 // Restore persistent override values. 235 PersistableBundle config = restoreConfigFromXml( 236 mPlatformCarrierConfigPackage, OVERRIDE_PACKAGE_ADDITION, phoneId); 237 if (config != null) { 238 logd("Loaded persistent override config from XML. package=" 239 + mPlatformCarrierConfigPackage 240 + " phoneId=" + phoneId); 241 mPersistentOverrideConfigs[phoneId] = config; 242 } 243 244 config = restoreConfigFromXml(mPlatformCarrierConfigPackage, "", phoneId); 245 if (config != null) { 246 logd( 247 "Loaded config from XML. package=" 248 + mPlatformCarrierConfigPackage 249 + " phoneId=" 250 + phoneId); 251 mConfigFromDefaultApp[phoneId] = config; 252 Message newMsg = obtainMessage(EVENT_FETCH_DEFAULT_DONE, phoneId, -1); 253 newMsg.getData().putBoolean("loaded_from_xml", true); 254 mHandler.sendMessage(newMsg); 255 } else { 256 // No cached config, so fetch it from the default app. 257 if (bindToConfigPackage( 258 mPlatformCarrierConfigPackage, 259 phoneId, 260 EVENT_CONNECTED_TO_DEFAULT)) { 261 sendMessageDelayed( 262 obtainMessage(EVENT_BIND_DEFAULT_TIMEOUT, phoneId, -1), 263 BIND_TIMEOUT_MILLIS); 264 } else { 265 // Send broadcast if bind fails. 266 notifySubscriptionInfoUpdater(phoneId); 267 // TODO: We *must* call unbindService even if bindService returns false. 268 // (And possibly if SecurityException was thrown.) 269 loge("binding to default app: " 270 + mPlatformCarrierConfigPackage + " fails"); 271 } 272 } 273 break; 274 } 275 276 case EVENT_CONNECTED_TO_DEFAULT: { 277 removeMessages(EVENT_BIND_DEFAULT_TIMEOUT); 278 final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj; 279 // If new service connection has been created, unbind. 280 if (mServiceConnection[phoneId] != conn || conn.service == null) { 281 unbindIfBound(mContext, conn, phoneId); 282 break; 283 } 284 final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId); 285 // ResultReceiver callback will execute in this Handler's thread. 286 final ResultReceiver resultReceiver = 287 new ResultReceiver(this) { 288 @Override 289 public void onReceiveResult(int resultCode, Bundle resultData) { 290 unbindIfBound(mContext, conn, phoneId); 291 // If new service connection has been created, this is stale. 292 if (mServiceConnection[phoneId] != conn) { 293 loge("Received response for stale request."); 294 return; 295 } 296 removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT); 297 if (resultCode == RESULT_ERROR || resultData == null) { 298 // On error, abort config fetching. 299 loge("Failed to get carrier config"); 300 notifySubscriptionInfoUpdater(phoneId); 301 return; 302 } 303 PersistableBundle config = 304 resultData.getParcelable(KEY_CONFIG_BUNDLE); 305 saveConfigToXml(mPlatformCarrierConfigPackage, "", phoneId, 306 carrierId, config); 307 mConfigFromDefaultApp[phoneId] = config; 308 sendMessage( 309 obtainMessage( 310 EVENT_FETCH_DEFAULT_DONE, phoneId, -1)); 311 } 312 }; 313 // Now fetch the config asynchronously from the ICarrierService. 314 try { 315 ICarrierService carrierService = 316 ICarrierService.Stub.asInterface(conn.service); 317 carrierService.getCarrierConfig(carrierId, resultReceiver); 318 logdWithLocalLog("Fetch config for default app: " 319 + mPlatformCarrierConfigPackage 320 + " carrierid: " + carrierId.toString()); 321 } catch (RemoteException e) { 322 loge("Failed to get carrier config from default app: " + 323 mPlatformCarrierConfigPackage + " err: " + e.toString()); 324 unbindIfBound(mContext, conn, phoneId); 325 break; // So we don't set a timeout. 326 } 327 sendMessageDelayed( 328 obtainMessage(EVENT_FETCH_DEFAULT_TIMEOUT, phoneId, -1), 329 BIND_TIMEOUT_MILLIS); 330 break; 331 } 332 333 case EVENT_BIND_DEFAULT_TIMEOUT: 334 case EVENT_FETCH_DEFAULT_TIMEOUT: { 335 loge("Bind/fetch time out from " + mPlatformCarrierConfigPackage); 336 removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT); 337 // If we attempted to bind to the app, but the service connection is null due to 338 // the race condition that clear config event happens before bind/fetch complete 339 // then config was cleared while we were waiting and we should not continue. 340 if (mServiceConnection[phoneId] != null) { 341 // If a ResponseReceiver callback is in the queue when this happens, we will 342 // unbind twice and throw an exception. 343 unbindIfBound(mContext, mServiceConnection[phoneId], phoneId); 344 broadcastConfigChangedIntent(phoneId); 345 } 346 notifySubscriptionInfoUpdater(phoneId); 347 break; 348 } 349 350 case EVENT_FETCH_DEFAULT_DONE: { 351 // If we attempted to bind to the app, but the service connection is null, then 352 // config was cleared while we were waiting and we should not continue. 353 if (!msg.getData().getBoolean("loaded_from_xml", false) 354 && mServiceConnection[phoneId] == null) { 355 break; 356 } 357 final String carrierPackageName = getCarrierPackageForPhoneId(phoneId); 358 if (carrierPackageName != null) { 359 logd("Found carrier config app: " + carrierPackageName); 360 sendMessage(obtainMessage(EVENT_DO_FETCH_CARRIER, phoneId, -1)); 361 } else { 362 notifySubscriptionInfoUpdater(phoneId); 363 } 364 break; 365 } 366 367 case EVENT_DO_FETCH_CARRIER: { 368 final String carrierPackageName = getCarrierPackageForPhoneId(phoneId); 369 final PersistableBundle config = 370 restoreConfigFromXml(carrierPackageName, "", phoneId); 371 if (config != null) { 372 logd( 373 "Loaded config from XML. package=" 374 + carrierPackageName 375 + " phoneId=" 376 + phoneId); 377 mConfigFromCarrierApp[phoneId] = config; 378 Message newMsg = obtainMessage(EVENT_FETCH_CARRIER_DONE, phoneId, -1); 379 newMsg.getData().putBoolean("loaded_from_xml", true); 380 sendMessage(newMsg); 381 } else { 382 // No cached config, so fetch it from a carrier app. 383 if (carrierPackageName != null && bindToConfigPackage(carrierPackageName, 384 phoneId, EVENT_CONNECTED_TO_CARRIER)) { 385 sendMessageDelayed( 386 obtainMessage(EVENT_BIND_CARRIER_TIMEOUT, phoneId, -1), 387 BIND_TIMEOUT_MILLIS); 388 } else { 389 // Send broadcast if bind fails. 390 broadcastConfigChangedIntent(phoneId); 391 loge("Bind to carrier app: " + carrierPackageName + " fails"); 392 notifySubscriptionInfoUpdater(phoneId); 393 } 394 } 395 break; 396 } 397 398 case EVENT_CONNECTED_TO_CARRIER: { 399 removeMessages(EVENT_BIND_CARRIER_TIMEOUT); 400 final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj; 401 // If new service connection has been created, unbind. 402 if (mServiceConnection[phoneId] != conn || conn.service == null) { 403 unbindIfBound(mContext, conn, phoneId); 404 break; 405 } 406 final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId); 407 // ResultReceiver callback will execute in this Handler's thread. 408 final ResultReceiver resultReceiver = 409 new ResultReceiver(this) { 410 @Override 411 public void onReceiveResult(int resultCode, Bundle resultData) { 412 unbindIfBound(mContext, conn, phoneId); 413 // If new service connection has been created, this is stale. 414 if (mServiceConnection[phoneId] != conn) { 415 loge("Received response for stale request."); 416 return; 417 } 418 removeMessages(EVENT_FETCH_CARRIER_TIMEOUT); 419 if (resultCode == RESULT_ERROR || resultData == null) { 420 // On error, abort config fetching. 421 loge("Failed to get carrier config from carrier app: " 422 + getCarrierPackageForPhoneId(phoneId)); 423 broadcastConfigChangedIntent(phoneId); 424 notifySubscriptionInfoUpdater(phoneId); 425 return; 426 } 427 PersistableBundle config = 428 resultData.getParcelable(KEY_CONFIG_BUNDLE); 429 saveConfigToXml(getCarrierPackageForPhoneId(phoneId), "", 430 phoneId, carrierId, config); 431 mConfigFromCarrierApp[phoneId] = config; 432 sendMessage( 433 obtainMessage( 434 EVENT_FETCH_CARRIER_DONE, phoneId, -1)); 435 } 436 }; 437 // Now fetch the config asynchronously from the ICarrierService. 438 try { 439 ICarrierService carrierService = 440 ICarrierService.Stub.asInterface(conn.service); 441 carrierService.getCarrierConfig(carrierId, resultReceiver); 442 logdWithLocalLog("Fetch config for carrier app: " 443 + getCarrierPackageForPhoneId(phoneId) 444 + " carrierid: " + carrierId.toString()); 445 } catch (RemoteException e) { 446 loge("Failed to get carrier config: " + e.toString()); 447 unbindIfBound(mContext, conn, phoneId); 448 break; // So we don't set a timeout. 449 } 450 sendMessageDelayed( 451 obtainMessage(EVENT_FETCH_CARRIER_TIMEOUT, phoneId, -1), 452 BIND_TIMEOUT_MILLIS); 453 break; 454 } 455 456 case EVENT_BIND_CARRIER_TIMEOUT: 457 case EVENT_FETCH_CARRIER_TIMEOUT: { 458 loge("Bind/fetch from carrier app timeout"); 459 removeMessages(EVENT_FETCH_CARRIER_TIMEOUT); 460 // If we attempted to bind to the app, but the service connection is null due to 461 // the race condition that clear config event happens before bind/fetch complete 462 // then config was cleared while we were waiting and we should not continue. 463 if (mServiceConnection[phoneId] != null) { 464 // If a ResponseReceiver callback is in the queue when this happens, we will 465 // unbind twice and throw an exception. 466 unbindIfBound(mContext, mServiceConnection[phoneId], phoneId); 467 broadcastConfigChangedIntent(phoneId); 468 } 469 notifySubscriptionInfoUpdater(phoneId); 470 break; 471 } 472 case EVENT_FETCH_CARRIER_DONE: { 473 // If we attempted to bind to the app, but the service connection is null, then 474 // config was cleared while we were waiting and we should not continue. 475 if (!msg.getData().getBoolean("loaded_from_xml", false) 476 && mServiceConnection[phoneId] == null) { 477 break; 478 } 479 notifySubscriptionInfoUpdater(phoneId); 480 break; 481 } 482 483 case EVENT_CHECK_SYSTEM_UPDATE: { 484 SharedPreferences sharedPrefs = 485 PreferenceManager.getDefaultSharedPreferences(mContext); 486 final String lastFingerprint = sharedPrefs.getString(KEY_FINGERPRINT, null); 487 if (!Build.FINGERPRINT.equals(lastFingerprint)) { 488 logd( 489 "Build fingerprint changed. old: " 490 + lastFingerprint 491 + " new: " 492 + Build.FINGERPRINT); 493 clearCachedConfigForPackage(null); 494 sharedPrefs 495 .edit() 496 .putString(KEY_FINGERPRINT, Build.FINGERPRINT) 497 .apply(); 498 } 499 break; 500 } 501 502 case EVENT_SUBSCRIPTION_INFO_UPDATED: 503 broadcastConfigChangedIntent(phoneId); 504 break; 505 case EVENT_MULTI_SIM_CONFIG_CHANGED: 506 onMultiSimConfigChanged(); 507 break; 508 } 509 } 510 } 511 512 private final Handler mHandler; 513 514 /** 515 * Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast 516 * receiver for relevant events. 517 */ CarrierConfigLoader(Context context)518 private CarrierConfigLoader(Context context) { 519 mContext = context; 520 mPlatformCarrierConfigPackage = 521 mContext.getString(R.string.platform_carrier_config_package); 522 mHandler = new ConfigHandler(); 523 524 IntentFilter bootFilter = new IntentFilter(); 525 bootFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 526 context.registerReceiver(mBootReceiver, bootFilter); 527 528 // Register for package updates. Update app or uninstall app update will have all 3 intents, 529 // in the order or removed, added, replaced, all with extra_replace set to true. 530 IntentFilter pkgFilter = new IntentFilter(); 531 pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 532 pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 533 pkgFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); 534 pkgFilter.addDataScheme("package"); 535 context.registerReceiver(mPackageReceiver, pkgFilter); 536 537 int numPhones = TelephonyManager.from(context).getSupportedModemCount(); 538 mConfigFromDefaultApp = new PersistableBundle[numPhones]; 539 mConfigFromCarrierApp = new PersistableBundle[numPhones]; 540 mPersistentOverrideConfigs = new PersistableBundle[numPhones]; 541 mOverrideConfigs = new PersistableBundle[numPhones]; 542 mServiceConnection = new CarrierServiceConnection[numPhones]; 543 mServiceBound = new boolean[numPhones]; 544 mHasSentConfigChange = new boolean[numPhones]; 545 mFromSystemUnlocked = new boolean[numPhones]; 546 // Make this service available through ServiceManager. 547 ServiceManager.addService(Context.CARRIER_CONFIG_SERVICE, this); 548 logd("CarrierConfigLoader has started"); 549 mSubscriptionInfoUpdater = PhoneFactory.getSubscriptionInfoUpdater(); 550 mHandler.sendEmptyMessage(EVENT_CHECK_SYSTEM_UPDATE); 551 } 552 553 /** 554 * Initialize the singleton CarrierConfigLoader instance. 555 * 556 * This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}. 557 */ 558 /* package */ init(Context context)559 static CarrierConfigLoader init(Context context) { 560 synchronized (CarrierConfigLoader.class) { 561 if (sInstance == null) { 562 sInstance = new CarrierConfigLoader(context); 563 } else { 564 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance); 565 } 566 return sInstance; 567 } 568 } 569 clearConfigForPhone(int phoneId, boolean sendBroadcast)570 private void clearConfigForPhone(int phoneId, boolean sendBroadcast) { 571 /* Ignore clear configuration request if device is being shutdown. */ 572 Phone phone = PhoneFactory.getPhone(phoneId); 573 if (phone != null) { 574 if (phone.isShuttingDown()) { 575 return; 576 } 577 } 578 579 mConfigFromDefaultApp[phoneId] = null; 580 mConfigFromCarrierApp[phoneId] = null; 581 mServiceConnection[phoneId] = null; 582 mHasSentConfigChange[phoneId] = false; 583 584 if (sendBroadcast) broadcastConfigChangedIntent(phoneId, false); 585 } 586 notifySubscriptionInfoUpdater(int phoneId)587 private void notifySubscriptionInfoUpdater(int phoneId) { 588 String configPackagename; 589 PersistableBundle configToSend; 590 int carrierId = getSpecificCarrierIdForPhoneId(phoneId); 591 // Prefer the carrier privileged carrier app, but if there is not one, use the platform 592 // default carrier app. 593 if (mConfigFromCarrierApp[phoneId] != null) { 594 configPackagename = getCarrierPackageForPhoneId(phoneId); 595 configToSend = mConfigFromCarrierApp[phoneId]; 596 } else { 597 configPackagename = mPlatformCarrierConfigPackage; 598 configToSend = mConfigFromDefaultApp[phoneId]; 599 } 600 601 if (configToSend == null) { 602 configToSend = new PersistableBundle(); 603 } 604 605 // mOverrideConfigs is for testing. And it will override current configs. 606 PersistableBundle config = mOverrideConfigs[phoneId]; 607 if (config != null) { 608 configToSend = new PersistableBundle(configToSend); 609 configToSend.putAll(config); 610 } 611 612 mSubscriptionInfoUpdater.updateSubscriptionByCarrierConfigAndNotifyComplete( 613 phoneId, configPackagename, configToSend, 614 mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1)); 615 } 616 broadcastConfigChangedIntent(int phoneId)617 private void broadcastConfigChangedIntent(int phoneId) { 618 broadcastConfigChangedIntent(phoneId, true); 619 } 620 broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra)621 private void broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra) { 622 Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 623 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 624 Intent.FLAG_RECEIVER_FOREGROUND); 625 if (addSubIdExtra) { 626 int simApplicationState = TelephonyManager.SIM_STATE_UNKNOWN; 627 int[] subIds = SubscriptionManager.getSubId(phoneId); 628 if (!ArrayUtils.isEmpty(subIds)) { 629 TelephonyManager telMgr = TelephonyManager.from(mContext) 630 .createForSubscriptionId(subIds[0]); 631 simApplicationState = telMgr.getSimApplicationState(); 632 } 633 logd("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId 634 + " simApplicationState " + simApplicationState); 635 // Include subId/carrier id extra only if SIM records are loaded 636 if (simApplicationState != TelephonyManager.SIM_STATE_UNKNOWN 637 && simApplicationState != TelephonyManager.SIM_STATE_NOT_READY) { 638 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId); 639 intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID, 640 getSpecificCarrierIdForPhoneId(phoneId)); 641 intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, getCarrierIdForPhoneId(phoneId)); 642 } 643 } 644 intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId); 645 intent.putExtra(CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, 646 mFromSystemUnlocked[phoneId]); 647 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 648 int[] subIds = SubscriptionManager.getSubId(phoneId); 649 if (subIds != null && subIds.length > 0) { 650 logd("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId + ", subId=" + subIds[0]); 651 } else { 652 logd("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId); 653 } 654 mHasSentConfigChange[phoneId] = true; 655 mFromSystemUnlocked[phoneId] = false; 656 } 657 658 /** Binds to the default or carrier config app. */ bindToConfigPackage(String pkgName, int phoneId, int eventId)659 private boolean bindToConfigPackage(String pkgName, int phoneId, int eventId) { 660 logdWithLocalLog("Binding to " + pkgName + " for phone " + phoneId); 661 Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE); 662 carrierService.setPackage(pkgName); 663 mServiceConnection[phoneId] = new CarrierServiceConnection(phoneId, pkgName, eventId); 664 try { 665 if (mContext.bindService(carrierService, mServiceConnection[phoneId], 666 Context.BIND_AUTO_CREATE)) { 667 mServiceBound[phoneId] = true; 668 return true; 669 } else { 670 return false; 671 } 672 } catch (SecurityException ex) { 673 return false; 674 } 675 } 676 getCarrierIdentifierForPhoneId(int phoneId)677 private CarrierIdentifier getCarrierIdentifierForPhoneId(int phoneId) { 678 String mcc = ""; 679 String mnc = ""; 680 String imsi = ""; 681 String gid1 = ""; 682 String gid2 = ""; 683 String spn = TelephonyManager.from(mContext).getSimOperatorNameForPhone(phoneId); 684 String simOperator = TelephonyManager.from(mContext).getSimOperatorNumericForPhone(phoneId); 685 int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 686 int specificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 687 // A valid simOperator should be 5 or 6 digits, depending on the length of the MNC. 688 if (simOperator != null && simOperator.length() >= 3) { 689 mcc = simOperator.substring(0, 3); 690 mnc = simOperator.substring(3); 691 } 692 Phone phone = PhoneFactory.getPhone(phoneId); 693 if (phone != null) { 694 imsi = phone.getSubscriberId(); 695 gid1 = phone.getGroupIdLevel1(); 696 gid2 = phone.getGroupIdLevel2(); 697 carrierId = phone.getCarrierId(); 698 specificCarrierId = phone.getSpecificCarrierId(); 699 } 700 return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2, carrierId, specificCarrierId); 701 } 702 703 /** Returns the package name of a priveleged carrier app, or null if there is none. */ getCarrierPackageForPhoneId(int phoneId)704 private String getCarrierPackageForPhoneId(int phoneId) { 705 List<String> carrierPackageNames = TelephonyManager.from(mContext) 706 .getCarrierPackageNamesForIntentAndPhone( 707 new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId); 708 if (carrierPackageNames != null && carrierPackageNames.size() > 0) { 709 return carrierPackageNames.get(0); 710 } else { 711 return null; 712 } 713 } 714 getIccIdForPhoneId(int phoneId)715 private String getIccIdForPhoneId(int phoneId) { 716 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 717 return null; 718 } 719 Phone phone = PhoneFactory.getPhone(phoneId); 720 if (phone == null) { 721 return null; 722 } 723 return phone.getIccSerialNumber(); 724 } 725 726 /** 727 * Get the sim specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()} 728 */ getSpecificCarrierIdForPhoneId(int phoneId)729 private int getSpecificCarrierIdForPhoneId(int phoneId) { 730 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 731 return TelephonyManager.UNKNOWN_CARRIER_ID; 732 } 733 Phone phone = PhoneFactory.getPhone(phoneId); 734 if (phone == null) { 735 return TelephonyManager.UNKNOWN_CARRIER_ID; 736 } 737 return phone.getSpecificCarrierId(); 738 } 739 740 /** 741 * Get the sim carrier id {@link TelephonyManager#getSimCarrierId() } 742 */ getCarrierIdForPhoneId(int phoneId)743 private int getCarrierIdForPhoneId(int phoneId) { 744 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 745 return TelephonyManager.UNKNOWN_CARRIER_ID; 746 } 747 Phone phone = PhoneFactory.getPhone(phoneId); 748 if (phone == null) { 749 return TelephonyManager.UNKNOWN_CARRIER_ID; 750 } 751 return phone.getCarrierId(); 752 } 753 754 /** 755 * Writes a bundle to an XML file. 756 * 757 * The bundle will be written to a file named after the package name, ICCID and 758 * specific carrier id {@link TelephonyManager#getSimSpecificCarrierId()}. the same carrier 759 * should have a single copy of XML file named after carrier id. However, it's still possible 760 * that platform doesn't recognize the current sim carrier, we will use iccid + carrierid as 761 * the canonical file name. carrierid can also handle the cases SIM OTA resolves to different 762 * carrier while iccid remains the same. 763 * 764 * The file can be restored later with {@link @restoreConfigFromXml}. The XML output will 765 * include the bundle and the current version of the specified package. 766 * 767 * In case of errors or invalid input, no file will be written. 768 * 769 * @param packageName the name of the package from which we fetched this bundle. 770 * @param extraString An extra string to be used in the XML file name. 771 * @param phoneId the phone ID. 772 * @param carrierId contains all carrier-identifying information. 773 * @param config the bundle to be written. Null will be treated as an empty bundle. 774 */ saveConfigToXml(String packageName, @NonNull String extraString, int phoneId, CarrierIdentifier carrierId, PersistableBundle config)775 private void saveConfigToXml(String packageName, @NonNull String extraString, int phoneId, 776 CarrierIdentifier carrierId, PersistableBundle config) { 777 if (SubscriptionManager.getSimStateForSlotIndex(phoneId) 778 != TelephonyManager.SIM_STATE_LOADED) { 779 loge("Skip save config because SIM records are not loaded."); 780 return; 781 } 782 783 final String iccid = getIccIdForPhoneId(phoneId); 784 final int cid = carrierId.getSpecificCarrierId(); 785 if (packageName == null || iccid == null) { 786 loge("Cannot save config with null packageName or iccid."); 787 return; 788 } 789 // b/32668103 Only save to file if config isn't empty. 790 // In case of failure, not caching an empty bundle will 791 // try loading config again on next power on or sim loaded. 792 // Downside is for genuinely empty bundle, will bind and load 793 // on every power on. 794 if (config == null || config.isEmpty()) { 795 return; 796 } 797 798 final String version = getPackageVersion(packageName); 799 if (version == null) { 800 loge("Failed to get package version for: " + packageName); 801 return; 802 } 803 804 logdWithLocalLog( 805 "Save config to xml, packagename: " + packageName + " phoneId: " + phoneId); 806 807 FileOutputStream outFile = null; 808 try { 809 outFile = new FileOutputStream( 810 new File(mContext.getFilesDir(), 811 getFilenameForConfig(packageName, extraString, iccid, cid))); 812 config.putString(KEY_VERSION, version); 813 config.writeToStream(outFile); 814 outFile.flush(); 815 outFile.close(); 816 } catch (IOException e) { 817 loge(e.toString()); 818 } 819 } 820 821 /** 822 * Reads a bundle from an XML file. 823 * 824 * This restores a bundle that was written with {@link #saveConfigToXml}. This returns the saved 825 * config bundle for the given package and phone ID. 826 * 827 * In case of errors, or if the saved config is from a different package version than the 828 * current version, then null will be returned. 829 * 830 * @param packageName the name of the package from which we fetched this bundle. 831 * @param extraString An extra string to be used in the XML file name. 832 * @param phoneId the phone ID. 833 * @return the bundle from the XML file. Returns null if there is no saved config, the saved 834 * version does not match, or reading config fails. 835 */ restoreConfigFromXml(String packageName, @NonNull String extraString, int phoneId)836 private PersistableBundle restoreConfigFromXml(String packageName, @NonNull String extraString, 837 int phoneId) { 838 final String version = getPackageVersion(packageName); 839 if (version == null) { 840 loge("Failed to get package version for: " + packageName); 841 return null; 842 } 843 if (SubscriptionManager.getSimStateForSlotIndex(phoneId) 844 != TelephonyManager.SIM_STATE_LOADED) { 845 loge("Skip restoring config because SIM records are not yet loaded."); 846 return null; 847 } 848 849 final String iccid = getIccIdForPhoneId(phoneId); 850 final int cid = getSpecificCarrierIdForPhoneId(phoneId); 851 if (packageName == null || iccid == null) { 852 loge("Cannot restore config with null packageName or iccid."); 853 return null; 854 } 855 856 PersistableBundle restoredBundle = null; 857 File file = null; 858 FileInputStream inFile = null; 859 try { 860 file = new File(mContext.getFilesDir(), 861 getFilenameForConfig(packageName, extraString, iccid, cid)); 862 inFile = new FileInputStream(file); 863 864 restoredBundle = PersistableBundle.readFromStream(inFile); 865 String savedVersion = restoredBundle.getString(KEY_VERSION); 866 restoredBundle.remove(KEY_VERSION); 867 868 if (!version.equals(savedVersion)) { 869 loge("Saved version mismatch: " + version + " vs " + savedVersion); 870 restoredBundle = null; 871 } 872 873 inFile.close(); 874 } catch (FileNotFoundException e) { 875 // Missing file is normal occurrence that might occur with a new sim or when restoring 876 // an override file during boot and should not be treated as an error. 877 if (file != null) logd("File not found: " + file.getPath()); 878 } catch (IOException e) { 879 loge(e.toString()); 880 } 881 882 return restoredBundle; 883 } 884 885 /** 886 * Clears cached carrier config. 887 * This deletes all saved XML files associated with the given package name. If packageName is 888 * null, then it deletes all saved XML files. 889 * 890 * @param packageName the name of a carrier package, or null if all cached config should be 891 * cleared. 892 * @return true iff one or more files were deleted. 893 */ clearCachedConfigForPackage(final String packageName)894 private boolean clearCachedConfigForPackage(final String packageName) { 895 File dir = mContext.getFilesDir(); 896 File[] packageFiles = dir.listFiles(new FilenameFilter() { 897 public boolean accept(File dir, String filename) { 898 if (packageName != null) { 899 return filename.startsWith("carrierconfig-" + packageName + "-"); 900 } else { 901 return filename.startsWith("carrierconfig-"); 902 } 903 } 904 }); 905 if (packageFiles == null || packageFiles.length < 1) return false; 906 for (File f : packageFiles) { 907 logd("Deleting " + f.getName()); 908 f.delete(); 909 } 910 return true; 911 } 912 913 /** Builds a canonical file name for a config file. */ getFilenameForConfig(@onNull String packageName, @NonNull String extraString, @NonNull String iccid, int cid)914 private String getFilenameForConfig(@NonNull String packageName, @NonNull String extraString, 915 @NonNull String iccid, int cid) { 916 // the same carrier should have a single copy of XML file named after carrier id. 917 // However, it's still possible that platform doesn't recognize the current sim carrier, 918 // we will use iccid + carrierid as the canonical file name. carrierid can also handle the 919 // cases SIM OTA resolves to different carrier while iccid remains the same. 920 return "carrierconfig-" + packageName + extraString + "-" + iccid + "-" + cid + ".xml"; 921 } 922 923 /** Return the current version code of a package, or null if the name is not found. */ getPackageVersion(String packageName)924 private String getPackageVersion(String packageName) { 925 try { 926 PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0); 927 return Long.toString(info.getLongVersionCode()); 928 } catch (PackageManager.NameNotFoundException e) { 929 return null; 930 } 931 } 932 933 /** 934 * Read up to date config. 935 * 936 * This reads config bundles for the given phoneId. That means getting the latest bundle from 937 * the default app and a privileged carrier app, if present. This will not bind to an app if we 938 * have a saved config file to use instead. 939 */ updateConfigForPhoneId(int phoneId)940 private void updateConfigForPhoneId(int phoneId) { 941 // Clear in-memory cache for carrier app config, so when carrier app gets uninstalled, no 942 // stale config is left. 943 if (mConfigFromCarrierApp[phoneId] != null && 944 getCarrierPackageForPhoneId(phoneId) == null) { 945 mConfigFromCarrierApp[phoneId] = null; 946 } 947 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DO_FETCH_DEFAULT, phoneId, -1)); 948 } 949 onMultiSimConfigChanged()950 private void onMultiSimConfigChanged() { 951 for (int i = TelephonyManager.from(mContext).getActiveModemCount(); 952 i < mConfigFromDefaultApp.length; i++) { 953 clearConfigForPhone(i, false); 954 } 955 } 956 957 @Override 958 @NonNull getConfigForSubId(int subId, String callingPackage)959 public PersistableBundle getConfigForSubId(int subId, String callingPackage) { 960 return getConfigForSubIdWithFeature(subId, callingPackage, null); 961 } 962 963 @Override 964 @NonNull getConfigForSubIdWithFeature(int subId, String callingPackage, String callingFeatureId)965 public PersistableBundle getConfigForSubIdWithFeature(int subId, String callingPackage, 966 String callingFeatureId) { 967 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage, 968 callingFeatureId, "getCarrierConfig")) { 969 return new PersistableBundle(); 970 } 971 972 int phoneId = SubscriptionManager.getPhoneId(subId); 973 PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig(); 974 if (SubscriptionManager.isValidPhoneId(phoneId)) { 975 PersistableBundle config = mConfigFromDefaultApp[phoneId]; 976 if (config != null) { 977 retConfig.putAll(config); 978 if (getCarrierPackageForPhoneId(phoneId) == null) { 979 retConfig.putBoolean( 980 CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); 981 } 982 } 983 config = mConfigFromCarrierApp[phoneId]; 984 if (config != null) { 985 retConfig.putAll(config); 986 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); 987 } 988 config = mPersistentOverrideConfigs[phoneId]; 989 if (config != null) { 990 retConfig.putAll(config); 991 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); 992 } 993 config = mOverrideConfigs[phoneId]; 994 if (config != null) { 995 retConfig.putAll(config); 996 } 997 } 998 return retConfig; 999 } 1000 1001 @Override overrideConfig(int subscriptionId, @Nullable PersistableBundle overrides, boolean persistent)1002 public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrides, 1003 boolean persistent) { 1004 mContext.enforceCallingOrSelfPermission( 1005 android.Manifest.permission.MODIFY_PHONE_STATE, null); 1006 //TODO: Also check for SHELL UID to restrict this method to testing only (b/131326259) 1007 int phoneId = SubscriptionManager.getPhoneId(subscriptionId); 1008 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1009 logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId); 1010 return; 1011 } 1012 overrideConfig(mOverrideConfigs, phoneId, overrides); 1013 1014 if (persistent) { 1015 overrideConfig(mPersistentOverrideConfigs, phoneId, overrides); 1016 1017 if (overrides != null) { 1018 final CarrierIdentifier carrierId = getCarrierIdentifierForPhoneId(phoneId); 1019 saveConfigToXml(mPlatformCarrierConfigPackage, OVERRIDE_PACKAGE_ADDITION, phoneId, 1020 carrierId, mPersistentOverrideConfigs[phoneId]); 1021 } else { 1022 final String iccid = getIccIdForPhoneId(phoneId); 1023 final int cid = getSpecificCarrierIdForPhoneId(phoneId); 1024 String fileName = getFilenameForConfig(mPlatformCarrierConfigPackage, 1025 OVERRIDE_PACKAGE_ADDITION, iccid, cid); 1026 File fileToDelete = new File(mContext.getFilesDir(), fileName); 1027 fileToDelete.delete(); 1028 } 1029 } 1030 notifySubscriptionInfoUpdater(phoneId); 1031 } 1032 overrideConfig(@onNull PersistableBundle[] currentOverrides, int phoneId, @Nullable PersistableBundle overrides)1033 private void overrideConfig(@NonNull PersistableBundle[] currentOverrides, int phoneId, 1034 @Nullable PersistableBundle overrides) { 1035 if (overrides == null) { 1036 currentOverrides[phoneId] = new PersistableBundle(); 1037 } else if (currentOverrides[phoneId] == null) { 1038 currentOverrides[phoneId] = overrides; 1039 } else { 1040 currentOverrides[phoneId].putAll(overrides); 1041 } 1042 } 1043 1044 @Override notifyConfigChangedForSubId(int subId)1045 public void notifyConfigChangedForSubId(int subId) { 1046 int phoneId = SubscriptionManager.getPhoneId(subId); 1047 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1048 logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subId); 1049 return; 1050 } 1051 1052 // Requires the calling app to be either a carrier privileged app for this subId or 1053 // system privileged app with MODIFY_PHONE_STATE permission. 1054 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mContext, subId, 1055 "Require carrier privileges or MODIFY_PHONE_STATE permission."); 1056 1057 // This method should block until deleting has completed, so that an error which prevents us 1058 // from clearing the cache is passed back to the carrier app. With the files successfully 1059 // deleted, this can return and we will eventually bind to the carrier app. 1060 String callingPackageName = mContext.getPackageManager().getNameForUid( 1061 Binder.getCallingUid()); 1062 clearCachedConfigForPackage(callingPackageName); 1063 updateConfigForPhoneId(phoneId); 1064 } 1065 1066 @Override updateConfigForPhoneId(int phoneId, String simState)1067 public void updateConfigForPhoneId(int phoneId, String simState) { 1068 mContext.enforceCallingOrSelfPermission( 1069 android.Manifest.permission.MODIFY_PHONE_STATE, null); 1070 logdWithLocalLog("Update config for phoneId: " + phoneId + " simState: " + simState); 1071 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1072 return; 1073 } 1074 // requires Java 7 for switch on string. 1075 switch (simState) { 1076 case IccCardConstants.INTENT_VALUE_ICC_ABSENT: 1077 case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR: 1078 case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED: 1079 case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN: 1080 case IccCardConstants.INTENT_VALUE_ICC_NOT_READY: 1081 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_CONFIG, phoneId, -1)); 1082 break; 1083 case IccCardConstants.INTENT_VALUE_ICC_LOADED: 1084 case IccCardConstants.INTENT_VALUE_ICC_LOCKED: 1085 updateConfigForPhoneId(phoneId); 1086 break; 1087 } 1088 } 1089 1090 @Override getDefaultCarrierServicePackageName()1091 public String getDefaultCarrierServicePackageName() { 1092 mContext.enforceCallingOrSelfPermission( 1093 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1094 "getDefaultCarrierServicePackageName"); 1095 return mPlatformCarrierConfigPackage; 1096 } 1097 unbindIfBound(Context context, CarrierServiceConnection conn, int phoneId)1098 private void unbindIfBound(Context context, CarrierServiceConnection conn, 1099 int phoneId) { 1100 if (mServiceBound[phoneId]) { 1101 mServiceBound[phoneId] = false; 1102 context.unbindService(conn); 1103 } 1104 } 1105 1106 /** 1107 * If {@code args} contains {@link #DUMP_ARG_REQUESTING_PACKAGE} and a following package name, 1108 * we'll also call {@link IBinder#dump} on the default carrier service (if bound) and the 1109 * specified carrier service (if bound). Typically, this is done for connectivity bug reports 1110 * where we don't call {@code dumpsys activity service all-non-platform} because that contains 1111 * too much info, but we still want to let carrier apps include their diagnostics. 1112 */ 1113 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1114 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1115 IndentingPrintWriter indentPW = new IndentingPrintWriter(pw, " "); 1116 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1117 != PackageManager.PERMISSION_GRANTED) { 1118 indentPW.println("Permission Denial: can't dump carrierconfig from from pid=" 1119 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1120 return; 1121 } 1122 String requestingPackage = null; 1123 int requestingPackageIndex = ArrayUtils.indexOf(args, DUMP_ARG_REQUESTING_PACKAGE); 1124 if (requestingPackageIndex >= 0 && requestingPackageIndex < args.length - 1 1125 && !TextUtils.isEmpty(args[requestingPackageIndex + 1])) { 1126 requestingPackage = args[requestingPackageIndex + 1]; 1127 // Throws a SecurityException if the caller is impersonating another app in an effort to 1128 // dump extra info (which may contain PII the caller doesn't have a right to). 1129 enforceCallerIsSystemOrRequestingPackage(requestingPackage); 1130 } 1131 1132 indentPW.println("CarrierConfigLoader: " + this); 1133 for (int i = 0; i < TelephonyManager.from(mContext).getActiveModemCount(); i++) { 1134 indentPW.println("Phone Id = " + i); 1135 // display default values in CarrierConfigManager 1136 printConfig(CarrierConfigManager.getDefaultConfig(), indentPW, 1137 "Default Values from CarrierConfigManager"); 1138 // display ConfigFromDefaultApp 1139 printConfig(mConfigFromDefaultApp[i], indentPW, "mConfigFromDefaultApp"); 1140 // display ConfigFromCarrierApp 1141 printConfig(mConfigFromCarrierApp[i], indentPW, "mConfigFromCarrierApp"); 1142 printConfig(mPersistentOverrideConfigs[i], indentPW, "mPersistentOverrideConfigs"); 1143 printConfig(mOverrideConfigs[i], indentPW, "mOverrideConfigs"); 1144 } 1145 1146 indentPW.println("CarrierConfigLoadingLog="); 1147 mCarrierConfigLoadingLog.dump(fd, indentPW, args); 1148 1149 if (requestingPackage != null) { 1150 logd("Including default and requesting package " + requestingPackage 1151 + " carrier services in dump"); 1152 indentPW.println(""); 1153 indentPW.println("Connected services"); 1154 dumpCarrierServiceIfBound(fd, indentPW, "Default config package", 1155 mPlatformCarrierConfigPackage, false /* considerCarrierPrivileges */); 1156 dumpCarrierServiceIfBound(fd, indentPW, "Requesting package", requestingPackage, 1157 true /* considerCarrierPrivileges */); 1158 } 1159 } 1160 printConfig(PersistableBundle configApp, IndentingPrintWriter indentPW, String name)1161 private void printConfig(PersistableBundle configApp, IndentingPrintWriter indentPW, 1162 String name) { 1163 indentPW.increaseIndent(); 1164 if (configApp == null) { 1165 indentPW.println(name + " : null "); 1166 indentPW.decreaseIndent(); 1167 indentPW.println(""); 1168 return; 1169 } 1170 indentPW.println(name + " : "); 1171 List<String> sortedKeys = new ArrayList<String>(configApp.keySet()); 1172 Collections.sort(sortedKeys); 1173 indentPW.increaseIndent(); 1174 indentPW.increaseIndent(); 1175 for (String key : sortedKeys) { 1176 if (configApp.get(key) != null && configApp.get(key) instanceof Object[]) { 1177 indentPW.println(key + " = " + 1178 Arrays.toString((Object[]) configApp.get(key))); 1179 } else if (configApp.get(key) != null && configApp.get(key) instanceof int[]) { 1180 indentPW.println(key + " = " + Arrays.toString((int[]) configApp.get(key))); 1181 } else { 1182 indentPW.println(key + " = " + configApp.get(key)); 1183 } 1184 } 1185 indentPW.decreaseIndent(); 1186 indentPW.decreaseIndent(); 1187 indentPW.decreaseIndent(); 1188 indentPW.println(""); 1189 } 1190 1191 /** 1192 * Passes without problem when one of these conditions is true: 1193 * - The caller is a privileged UID (e.g. for dumpstate.cpp generating a bug report, where the 1194 * system knows the true caller plumbed in through the {@link android.os.BugreportManager} API). 1195 * - The caller's UID matches the supplied package. 1196 * 1197 * @throws SecurityException if none of the above conditions are met. 1198 */ enforceCallerIsSystemOrRequestingPackage(String requestingPackage)1199 private void enforceCallerIsSystemOrRequestingPackage(String requestingPackage) 1200 throws SecurityException { 1201 final int callingUid = Binder.getCallingUid(); 1202 if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID 1203 || callingUid == Process.SHELL_UID || callingUid == Process.PHONE_UID) { 1204 // Bug reports (dumpstate.cpp) run as SHELL, and let some other privileged UIDs through 1205 // as well. 1206 return; 1207 } 1208 // An app is trying to dump extra detail, block it if they aren't who they claim to be. 1209 AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); 1210 if (appOps == null) { 1211 throw new SecurityException("No AppOps"); 1212 } 1213 // Will throw a SecurityException if the UID and package don't match. 1214 appOps.checkPackage(callingUid, requestingPackage); 1215 } 1216 1217 /** 1218 * Searches for one or more appropriate {@link CarrierService} instances to dump based on the 1219 * current connections. 1220 * 1221 * @param targetPkgName the target package name to dump carrier services for 1222 * @param considerCarrierPrivileges if true, allow a carrier service to be dumped if it shares 1223 * carrier privileges with {@code targetPkgName}; 1224 * otherwise, only dump a carrier service if it is {@code 1225 * targetPkgName} 1226 */ dumpCarrierServiceIfBound(FileDescriptor fd, IndentingPrintWriter indentPW, String prefix, String targetPkgName, boolean considerCarrierPrivileges)1227 private void dumpCarrierServiceIfBound(FileDescriptor fd, IndentingPrintWriter indentPW, 1228 String prefix, String targetPkgName, boolean considerCarrierPrivileges) { 1229 // Null package is possible if it's early in the boot process, there was a recent crash, we 1230 // loaded the config from XML most recently, or a SIM slot is empty. Carrier apps with 1231 // long-lived bindings should typically get dumped here regardless. Even if an app is being 1232 // used for multiple phoneIds, we assume that it's smart enough to handle that on its own, 1233 // and that in most cases we'd just be dumping duplicate information and bloating a report. 1234 indentPW.increaseIndent(); 1235 indentPW.println(prefix + " : " + targetPkgName); 1236 Set<String> dumpedPkgNames = new ArraySet<>(mServiceConnection.length); 1237 for (CarrierServiceConnection connection : mServiceConnection) { 1238 if (connection == null || !SubscriptionManager.isValidPhoneId(connection.phoneId) 1239 || TextUtils.isEmpty(connection.pkgName)) { 1240 continue; 1241 } 1242 final String servicePkgName = connection.pkgName; 1243 // Note: we intentionally ignore system components here because we should NOT match the 1244 // shell caller that's typically used for bug reports via non-BugreportManager triggers. 1245 final boolean exactPackageMatch = TextUtils.equals(targetPkgName, servicePkgName); 1246 final boolean carrierPrivilegesMatch = 1247 considerCarrierPrivileges && hasCarrierPrivileges(targetPkgName, 1248 connection.phoneId); 1249 if (!exactPackageMatch && !carrierPrivilegesMatch) continue; 1250 // Make sure this service is actually alive before trying to dump it. We don't pay 1251 // attention to mServiceBound[connection.phoneId] because typically carrier apps will 1252 // request long-lived bindings, and even if we unbind the app, it may still be alive due 1253 // to CarrierServiceBindHelper. Pull it out as a reference so even if it gets set to 1254 // null within the ServiceConnection during unbinding we can avoid an NPE. 1255 final IBinder service = connection.service; 1256 if (service == null || !service.isBinderAlive() || !service.pingBinder()) continue; 1257 // We've got a live service. Last check is just to make sure we don't dump a package 1258 // multiple times. 1259 if (!dumpedPkgNames.add(servicePkgName)) continue; 1260 if (!exactPackageMatch) { 1261 logd(targetPkgName + " has carrier privileges on phoneId " + connection.phoneId 1262 + ", service provided by " + servicePkgName); 1263 indentPW.increaseIndent(); 1264 indentPW.println("Proxy : " + servicePkgName); 1265 indentPW.decreaseIndent(); 1266 } 1267 // Flush before we let the app output anything to ensure correct ordering of output. 1268 // Internally, Binder#dump calls flush on its printer after finishing so we don't 1269 // need to do anything after. 1270 indentPW.flush(); 1271 try { 1272 logd("Dumping " + servicePkgName); 1273 // We don't need to give the carrier service any args. 1274 connection.service.dump(fd, null /* args */); 1275 logd("Done with " + servicePkgName); 1276 } catch (RemoteException e) { 1277 logd("RemoteException from " + servicePkgName, e); 1278 indentPW.increaseIndent(); 1279 indentPW.println("RemoteException"); 1280 indentPW.increaseIndent(); 1281 e.printStackTrace(indentPW); 1282 indentPW.decreaseIndent(); 1283 indentPW.decreaseIndent(); 1284 // We won't retry this package again because now it's in dumpedPkgNames. 1285 } 1286 indentPW.println(""); 1287 } 1288 if (dumpedPkgNames.isEmpty()) { 1289 indentPW.increaseIndent(); 1290 indentPW.println("Not bound"); 1291 indentPW.decreaseIndent(); 1292 indentPW.println(""); 1293 } 1294 indentPW.decreaseIndent(); 1295 } 1296 hasCarrierPrivileges(String pkgName, int phoneId)1297 private boolean hasCarrierPrivileges(String pkgName, int phoneId) { 1298 int[] subIds = SubscriptionManager.getSubId(phoneId); 1299 if (ArrayUtils.isEmpty(subIds)) { 1300 return false; 1301 } 1302 return TelephonyManager.from(mContext).createForSubscriptionId( 1303 subIds[0]).checkCarrierPrivilegesForPackage(pkgName) 1304 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 1305 } 1306 1307 private class CarrierServiceConnection implements ServiceConnection { 1308 final int phoneId; 1309 final String pkgName; 1310 final int eventId; 1311 IBinder service; 1312 CarrierServiceConnection(int phoneId, String pkgName, int eventId)1313 CarrierServiceConnection(int phoneId, String pkgName, int eventId) { 1314 this.phoneId = phoneId; 1315 this.pkgName = pkgName; 1316 this.eventId = eventId; 1317 } 1318 1319 @Override onServiceConnected(ComponentName name, IBinder service)1320 public void onServiceConnected(ComponentName name, IBinder service) { 1321 logd("Connected to config app: " + name.flattenToShortString()); 1322 this.service = service; 1323 mHandler.sendMessage(mHandler.obtainMessage(eventId, phoneId, -1, this)); 1324 } 1325 1326 @Override onServiceDisconnected(ComponentName name)1327 public void onServiceDisconnected(ComponentName name) { 1328 logd("Disconnected from config app: " + name.flattenToShortString()); 1329 this.service = null; 1330 } 1331 1332 @Override onBindingDied(ComponentName name)1333 public void onBindingDied(ComponentName name) { 1334 logd("Binding died from config app: " + name.flattenToShortString()); 1335 this.service = null; 1336 } 1337 1338 @Override onNullBinding(ComponentName name)1339 public void onNullBinding(ComponentName name) { 1340 logd("Null binding from config app: " + name.flattenToShortString()); 1341 this.service = null; 1342 } 1343 } 1344 1345 private class ConfigLoaderBroadcastReceiver extends BroadcastReceiver { 1346 @Override onReceive(Context context, Intent intent)1347 public void onReceive(Context context, Intent intent) { 1348 String action = intent.getAction(); 1349 boolean replace = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); 1350 // If replace is true, only care ACTION_PACKAGE_REPLACED. 1351 if (replace && !Intent.ACTION_PACKAGE_REPLACED.equals(action)) { 1352 return; 1353 } 1354 1355 switch (action) { 1356 case Intent.ACTION_BOOT_COMPLETED: 1357 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_UNLOCKED, null)); 1358 break; 1359 1360 case Intent.ACTION_PACKAGE_ADDED: 1361 case Intent.ACTION_PACKAGE_REMOVED: 1362 case Intent.ACTION_PACKAGE_REPLACED: 1363 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 1364 String packageName = mContext.getPackageManager().getNameForUid(uid); 1365 if (packageName != null) { 1366 // We don't have a phoneId for arg1. 1367 mHandler.sendMessage( 1368 mHandler.obtainMessage(EVENT_PACKAGE_CHANGED, packageName)); 1369 } 1370 break; 1371 } 1372 } 1373 } 1374 logd(String msg)1375 private void logd(String msg) { 1376 Log.d(LOG_TAG, msg); 1377 } 1378 logd(String msg, Throwable tr)1379 private void logd(String msg, Throwable tr) { 1380 Log.d(LOG_TAG, msg, tr); 1381 } 1382 logdWithLocalLog(String msg)1383 private void logdWithLocalLog(String msg) { 1384 Log.d(LOG_TAG, msg); 1385 mCarrierConfigLoadingLog.log(msg); 1386 } 1387 loge(String msg)1388 private void loge(String msg) { 1389 Log.e(LOG_TAG, msg); 1390 mCarrierConfigLoadingLog.log(msg); 1391 } 1392 } 1393