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.Manifest.permission.READ_PHONE_STATE; 20 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; 21 import static android.service.carrier.CarrierService.ICarrierServiceWrapper.KEY_CONFIG_BUNDLE; 22 import static android.service.carrier.CarrierService.ICarrierServiceWrapper.RESULT_ERROR; 23 24 import android.annotation.NonNull; 25 import android.app.ActivityManager; 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.content.ServiceConnection; 32 import android.content.SharedPreferences; 33 import android.content.pm.PackageInfo; 34 import android.content.pm.PackageManager; 35 import android.os.Binder; 36 import android.os.Build; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.os.IBinder; 40 import android.os.Message; 41 import android.os.PersistableBundle; 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.util.Log; 54 55 import com.android.internal.telephony.ICarrierConfigLoader; 56 import com.android.internal.telephony.IccCardConstants; 57 import com.android.internal.telephony.Phone; 58 import com.android.internal.telephony.PhoneFactory; 59 import com.android.internal.telephony.TelephonyPermissions; 60 import com.android.internal.util.FastXmlSerializer; 61 import com.android.internal.util.IndentingPrintWriter; 62 63 import org.xmlpull.v1.XmlPullParser; 64 import org.xmlpull.v1.XmlPullParserException; 65 import org.xmlpull.v1.XmlPullParserFactory; 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 80 /** 81 * CarrierConfigLoader binds to privileged carrier apps to fetch carrier config overlays. 82 */ 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 // Service connection for binding to config app. 99 private CarrierServiceConnection[] mServiceConnection; 100 // Whether we have sent config change bcast for each phone id. 101 private boolean[] mHasSentConfigChange; 102 103 // Broadcast receiver for Boot intents, register intent filter in construtor. 104 private final BroadcastReceiver mBootReceiver = new ConfigLoaderBroadcastReceiver(); 105 // Broadcast receiver for SIM and pkg intents, register intent filter in constructor. 106 private final BroadcastReceiver mPackageReceiver = new ConfigLoaderBroadcastReceiver(); 107 108 // Message codes; see mHandler below. 109 // Request from SubscriptionInfoUpdater when SIM becomes absent or error. 110 private static final int EVENT_CLEAR_CONFIG = 0; 111 // Has connected to default app. 112 private static final int EVENT_CONNECTED_TO_DEFAULT = 3; 113 // Has connected to carrier app. 114 private static final int EVENT_CONNECTED_TO_CARRIER = 4; 115 // Config has been loaded from default app (or cache). 116 private static final int EVENT_FETCH_DEFAULT_DONE = 5; 117 // Config has been loaded from carrier app (or cache). 118 private static final int EVENT_FETCH_CARRIER_DONE = 6; 119 // Attempt to fetch from default app or read from XML. 120 private static final int EVENT_DO_FETCH_DEFAULT = 7; 121 // Attempt to fetch from carrier app or read from XML. 122 private static final int EVENT_DO_FETCH_CARRIER = 8; 123 // A package has been installed, uninstalled, or updated. 124 private static final int EVENT_PACKAGE_CHANGED = 9; 125 // Bind timed out for the default app. 126 private static final int EVENT_BIND_DEFAULT_TIMEOUT = 10; 127 // Bind timed out for a carrier app. 128 private static final int EVENT_BIND_CARRIER_TIMEOUT = 11; 129 // Check if the system fingerprint has changed. 130 private static final int EVENT_CHECK_SYSTEM_UPDATE = 12; 131 // Rerun carrier config binding after system is unlocked. 132 private static final int EVENT_SYSTEM_UNLOCKED = 13; 133 // Fetching config timed out from the default app. 134 private static final int EVENT_FETCH_DEFAULT_TIMEOUT = 14; 135 // Fetching config timed out from a carrier app. 136 private static final int EVENT_FETCH_CARRIER_TIMEOUT = 15; 137 138 private static final int BIND_TIMEOUT_MILLIS = 30000; 139 140 // Tags used for saving and restoring XML documents. 141 private static final String TAG_DOCUMENT = "carrier_config"; 142 private static final String TAG_VERSION = "package_version"; 143 private static final String TAG_BUNDLE = "bundle_data"; 144 145 // SharedPreferences key for last known build fingerprint. 146 private static final String KEY_FINGERPRINT = "build_fingerprint"; 147 148 // Handler to process various events. 149 // 150 // For each phoneId, the event sequence should be: 151 // fetch default, connected to default, fetch default (async), fetch default done, 152 // fetch carrier, connected to carrier, fetch carrier (async), fetch carrier done. 153 // 154 // If there is a saved config file for either the default app or the carrier app, we skip 155 // binding to the app and go straight from fetch to loaded. 156 // 157 // At any time, at most one connection is active. If events are not in this order, previous 158 // connection will be unbound, so only latest event takes effect. 159 // 160 // We broadcast ACTION_CARRIER_CONFIG_CHANGED after: 161 // 1. loading from carrier app (even if read from a file) 162 // 2. loading from default app if there is no carrier app (even if read from a file) 163 // 3. clearing config (e.g. due to sim removal) 164 // 4. encountering bind or IPC error 165 private class ConfigHandler extends Handler { 166 @Override handleMessage(Message msg)167 public void handleMessage(Message msg) { 168 final int phoneId = msg.arg1; 169 log("mHandler: " + msg.what + " phoneId: " + phoneId); 170 switch (msg.what) { 171 case EVENT_CLEAR_CONFIG: 172 { 173 /* Ignore clear configuration request if device is being shutdown. */ 174 Phone phone = PhoneFactory.getPhone(phoneId); 175 if (phone != null) { 176 if (phone.isShuttingDown()) { 177 break; 178 } 179 } 180 181 if (mConfigFromDefaultApp[phoneId] == null 182 && mConfigFromCarrierApp[phoneId] == null) break; 183 184 mConfigFromDefaultApp[phoneId] = null; 185 mConfigFromCarrierApp[phoneId] = null; 186 mServiceConnection[phoneId] = null; 187 broadcastConfigChangedIntent(phoneId, false); 188 break; 189 } 190 191 case EVENT_SYSTEM_UNLOCKED: 192 { 193 for (int i = 0; i < TelephonyManager.from(mContext).getPhoneCount(); ++i) { 194 // When user unlock device, we should only try to send broadcast again if we 195 // have sent it before unlock. This will avoid we try to load carrier config 196 // when SIM is still loading when unlock happens. 197 if (mHasSentConfigChange[i]) { 198 updateConfigForPhoneId(i); 199 } 200 } 201 break; 202 } 203 204 case EVENT_PACKAGE_CHANGED: 205 { 206 final String carrierPackageName = (String) msg.obj; 207 // Only update if there are cached config removed to avoid updating config for 208 // unrelated packages. 209 if (clearCachedConfigForPackage(carrierPackageName)) { 210 int numPhones = TelephonyManager.from(mContext).getPhoneCount(); 211 for (int i = 0; i < numPhones; ++i) { 212 updateConfigForPhoneId(i); 213 } 214 } 215 break; 216 } 217 218 case EVENT_DO_FETCH_DEFAULT: 219 { 220 final String iccid = getIccIdForPhoneId(phoneId); 221 final PersistableBundle config = 222 restoreConfigFromXml(mPlatformCarrierConfigPackage, iccid); 223 if (config != null) { 224 log( 225 "Loaded config from XML. package=" 226 + mPlatformCarrierConfigPackage 227 + " phoneId=" 228 + phoneId); 229 mConfigFromDefaultApp[phoneId] = config; 230 Message newMsg = obtainMessage(EVENT_FETCH_DEFAULT_DONE, phoneId, -1); 231 newMsg.getData().putBoolean("loaded_from_xml", true); 232 mHandler.sendMessage(newMsg); 233 } else { 234 // No cached config, so fetch it from the default app. 235 if (bindToConfigPackage( 236 mPlatformCarrierConfigPackage, 237 phoneId, 238 EVENT_CONNECTED_TO_DEFAULT)) { 239 sendMessageDelayed( 240 obtainMessage(EVENT_BIND_DEFAULT_TIMEOUT, phoneId, -1), 241 BIND_TIMEOUT_MILLIS); 242 } else { 243 // Send broadcast if bind fails. 244 broadcastConfigChangedIntent(phoneId); 245 // TODO: We *must* call unbindService even if bindService returns false. 246 // (And possibly if SecurityException was thrown.) 247 } 248 } 249 break; 250 } 251 252 case EVENT_CONNECTED_TO_DEFAULT: 253 { 254 removeMessages(EVENT_BIND_DEFAULT_TIMEOUT); 255 final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj; 256 // If new service connection has been created, unbind. 257 if (mServiceConnection[phoneId] != conn || conn.service == null) { 258 mContext.unbindService(conn); 259 break; 260 } 261 final CarrierIdentifier carrierId = getCarrierIdForPhoneId(phoneId); 262 final String iccid = getIccIdForPhoneId(phoneId); 263 // ResultReceiver callback will execute in this Handler's thread. 264 final ResultReceiver resultReceiver = 265 new ResultReceiver(this) { 266 @Override 267 public void onReceiveResult(int resultCode, Bundle resultData) { 268 mContext.unbindService(conn); 269 // If new service connection has been created, this is stale. 270 if (mServiceConnection[phoneId] != conn) { 271 loge("Received response for stale request."); 272 return; 273 } 274 removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT); 275 if (resultCode == RESULT_ERROR || resultData == null) { 276 // On error, abort config fetching. 277 loge("Failed to get carrier config"); 278 broadcastConfigChangedIntent(phoneId); 279 return; 280 } 281 PersistableBundle config = 282 resultData.getParcelable(KEY_CONFIG_BUNDLE); 283 saveConfigToXml( 284 mPlatformCarrierConfigPackage, iccid, config); 285 mConfigFromDefaultApp[phoneId] = config; 286 sendMessage( 287 obtainMessage( 288 EVENT_FETCH_DEFAULT_DONE, phoneId, -1)); 289 } 290 }; 291 // Now fetch the config asynchronously from the ICarrierService. 292 try { 293 ICarrierService carrierService = 294 ICarrierService.Stub.asInterface(conn.service); 295 carrierService.getCarrierConfig(carrierId, resultReceiver); 296 } catch (RemoteException e) { 297 loge("Failed to get carrier config: " + e.toString()); 298 mContext.unbindService(conn); 299 break; // So we don't set a timeout. 300 } 301 sendMessageDelayed( 302 obtainMessage(EVENT_FETCH_DEFAULT_TIMEOUT, phoneId, -1), 303 BIND_TIMEOUT_MILLIS); 304 break; 305 } 306 307 case EVENT_BIND_DEFAULT_TIMEOUT: 308 case EVENT_FETCH_DEFAULT_TIMEOUT: 309 { 310 // If a ResponseReceiver callback is in the queue when this happens, we will 311 // unbind twice and throw an exception. 312 mContext.unbindService(mServiceConnection[phoneId]); 313 removeMessages(EVENT_FETCH_DEFAULT_TIMEOUT); 314 broadcastConfigChangedIntent(phoneId); 315 break; 316 } 317 318 case EVENT_FETCH_DEFAULT_DONE: 319 { 320 // If we attempted to bind to the app, but the service connection is null, then 321 // config was cleared while we were waiting and we should not continue. 322 if (!msg.getData().getBoolean("loaded_from_xml", false) 323 && mServiceConnection[phoneId] == null) { 324 break; 325 } 326 final String carrierPackageName = getCarrierPackageForPhoneId(phoneId); 327 if (carrierPackageName != null) { 328 log("Found carrier config app: " + carrierPackageName); 329 sendMessage(obtainMessage(EVENT_DO_FETCH_CARRIER, phoneId)); 330 } else { 331 broadcastConfigChangedIntent(phoneId); 332 } 333 break; 334 } 335 336 case EVENT_DO_FETCH_CARRIER: 337 { 338 final String carrierPackageName = getCarrierPackageForPhoneId(phoneId); 339 final String iccid = getIccIdForPhoneId(phoneId); 340 final PersistableBundle config = 341 restoreConfigFromXml(carrierPackageName, iccid); 342 if (config != null) { 343 log( 344 "Loaded config from XML. package=" 345 + carrierPackageName 346 + " phoneId=" 347 + phoneId); 348 mConfigFromCarrierApp[phoneId] = config; 349 Message newMsg = obtainMessage(EVENT_FETCH_CARRIER_DONE, phoneId, -1); 350 newMsg.getData().putBoolean("loaded_from_xml", true); 351 sendMessage(newMsg); 352 } else { 353 // No cached config, so fetch it from a carrier app. 354 if (carrierPackageName != null 355 && bindToConfigPackage( 356 carrierPackageName, 357 phoneId, 358 EVENT_CONNECTED_TO_CARRIER)) { 359 sendMessageDelayed( 360 obtainMessage(EVENT_BIND_CARRIER_TIMEOUT, phoneId, -1), 361 BIND_TIMEOUT_MILLIS); 362 } else { 363 // Send broadcast if bind fails. 364 broadcastConfigChangedIntent(phoneId); 365 } 366 } 367 break; 368 } 369 370 case EVENT_CONNECTED_TO_CARRIER: 371 { 372 removeMessages(EVENT_BIND_CARRIER_TIMEOUT); 373 final CarrierServiceConnection conn = (CarrierServiceConnection) msg.obj; 374 // If new service connection has been created, unbind. 375 if (mServiceConnection[phoneId] != conn || conn.service == null) { 376 mContext.unbindService(conn); 377 break; 378 } 379 final CarrierIdentifier carrierId = getCarrierIdForPhoneId(phoneId); 380 final String iccid = getIccIdForPhoneId(phoneId); 381 // ResultReceiver callback will execute in this Handler's thread. 382 final ResultReceiver resultReceiver = 383 new ResultReceiver(this) { 384 @Override 385 public void onReceiveResult(int resultCode, Bundle resultData) { 386 mContext.unbindService(conn); 387 // If new service connection has been created, this is stale. 388 if (mServiceConnection[phoneId] != conn) { 389 loge("Received response for stale request."); 390 return; 391 } 392 removeMessages(EVENT_FETCH_CARRIER_TIMEOUT); 393 if (resultCode == RESULT_ERROR || resultData == null) { 394 // On error, abort config fetching. 395 loge("Failed to get carrier config"); 396 broadcastConfigChangedIntent(phoneId); 397 return; 398 } 399 PersistableBundle config = 400 resultData.getParcelable(KEY_CONFIG_BUNDLE); 401 saveConfigToXml( 402 getCarrierPackageForPhoneId(phoneId), iccid, config); 403 mConfigFromCarrierApp[phoneId] = config; 404 sendMessage( 405 obtainMessage( 406 EVENT_FETCH_CARRIER_DONE, phoneId, -1)); 407 } 408 }; 409 // Now fetch the config asynchronously from the ICarrierService. 410 try { 411 ICarrierService carrierService = 412 ICarrierService.Stub.asInterface(conn.service); 413 carrierService.getCarrierConfig(carrierId, resultReceiver); 414 } catch (RemoteException e) { 415 loge("Failed to get carrier config: " + e.toString()); 416 mContext.unbindService(conn); 417 break; // So we don't set a timeout. 418 } 419 sendMessageDelayed( 420 obtainMessage(EVENT_FETCH_CARRIER_TIMEOUT, phoneId, -1), 421 BIND_TIMEOUT_MILLIS); 422 break; 423 } 424 425 case EVENT_BIND_CARRIER_TIMEOUT: 426 case EVENT_FETCH_CARRIER_TIMEOUT: 427 { 428 // If a ResponseReceiver callback is in the queue when this happens, we will 429 // unbind twice and throw an exception. 430 mContext.unbindService(mServiceConnection[phoneId]); 431 removeMessages(EVENT_FETCH_CARRIER_TIMEOUT); 432 broadcastConfigChangedIntent(phoneId); 433 break; 434 } 435 436 case EVENT_FETCH_CARRIER_DONE: 437 { 438 // If we attempted to bind to the app, but the service connection is null, then 439 // config was cleared while we were waiting and we should not continue. 440 if (!msg.getData().getBoolean("loaded_from_xml", false) 441 && mServiceConnection[phoneId] == null) { 442 break; 443 } 444 broadcastConfigChangedIntent(phoneId); 445 break; 446 } 447 448 case EVENT_CHECK_SYSTEM_UPDATE: 449 { 450 SharedPreferences sharedPrefs = 451 PreferenceManager.getDefaultSharedPreferences(mContext); 452 final String lastFingerprint = sharedPrefs.getString(KEY_FINGERPRINT, null); 453 if (!Build.FINGERPRINT.equals(lastFingerprint)) { 454 log( 455 "Build fingerprint changed. old: " 456 + lastFingerprint 457 + " new: " 458 + Build.FINGERPRINT); 459 clearCachedConfigForPackage(null); 460 sharedPrefs 461 .edit() 462 .putString(KEY_FINGERPRINT, Build.FINGERPRINT) 463 .apply(); 464 } 465 break; 466 } 467 } 468 } 469 } 470 471 private final Handler mHandler; 472 473 /** 474 * Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast 475 * receiver for relevant events. 476 */ CarrierConfigLoader(Context context)477 private CarrierConfigLoader(Context context) { 478 mContext = context; 479 mPlatformCarrierConfigPackage = 480 mContext.getString(R.string.platform_carrier_config_package); 481 mHandler = new ConfigHandler(); 482 483 IntentFilter bootFilter = new IntentFilter(); 484 bootFilter.addAction(Intent.ACTION_BOOT_COMPLETED); 485 context.registerReceiver(mBootReceiver, bootFilter); 486 487 // Register for package updates. Update app or uninstall app update will have all 3 intents, 488 // in the order or removed, added, replaced, all with extra_replace set to true. 489 IntentFilter pkgFilter = new IntentFilter(); 490 pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 491 pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 492 pkgFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); 493 pkgFilter.addDataScheme("package"); 494 context.registerReceiverAsUser(mPackageReceiver, UserHandle.ALL, pkgFilter, null, null); 495 496 int numPhones = TelephonyManager.from(context).getPhoneCount(); 497 mConfigFromDefaultApp = new PersistableBundle[numPhones]; 498 mConfigFromCarrierApp = new PersistableBundle[numPhones]; 499 mServiceConnection = new CarrierServiceConnection[numPhones]; 500 mHasSentConfigChange = new boolean[numPhones]; 501 // Make this service available through ServiceManager. 502 ServiceManager.addService(Context.CARRIER_CONFIG_SERVICE, this); 503 log("CarrierConfigLoader has started"); 504 mHandler.sendEmptyMessage(EVENT_CHECK_SYSTEM_UPDATE); 505 } 506 507 /** 508 * Initialize the singleton CarrierConfigLoader instance. 509 * 510 * This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}. 511 */ 512 /* package */ init(Context context)513 static CarrierConfigLoader init(Context context) { 514 synchronized (CarrierConfigLoader.class) { 515 if (sInstance == null) { 516 sInstance = new CarrierConfigLoader(context); 517 } else { 518 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance); 519 } 520 return sInstance; 521 } 522 } 523 broadcastConfigChangedIntent(int phoneId)524 private void broadcastConfigChangedIntent(int phoneId) { 525 broadcastConfigChangedIntent(phoneId, true); 526 } 527 broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra)528 private void broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra) { 529 Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 530 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 531 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); 532 // Include subId extra only if SIM records are loaded 533 TelephonyManager telephonyManager = TelephonyManager.from(mContext); 534 int simApplicationState = telephonyManager.getSimApplicationState(); 535 if (addSubIdExtra && (simApplicationState != TelephonyManager.SIM_STATE_UNKNOWN 536 && simApplicationState != TelephonyManager.SIM_STATE_NOT_READY)) { 537 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId); 538 } 539 intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId); 540 ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL); 541 mHasSentConfigChange[phoneId] = true; 542 } 543 544 /** Binds to the default or carrier config app. */ bindToConfigPackage(String pkgName, int phoneId, int eventId)545 private boolean bindToConfigPackage(String pkgName, int phoneId, int eventId) { 546 log("Binding to " + pkgName + " for phone " + phoneId); 547 Intent carrierService = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE); 548 carrierService.setPackage(pkgName); 549 mServiceConnection[phoneId] = new CarrierServiceConnection(phoneId, eventId); 550 try { 551 return mContext.bindService(carrierService, mServiceConnection[phoneId], 552 Context.BIND_AUTO_CREATE); 553 } catch (SecurityException ex) { 554 return false; 555 } 556 } 557 getCarrierIdForPhoneId(int phoneId)558 private CarrierIdentifier getCarrierIdForPhoneId(int phoneId) { 559 String mcc = ""; 560 String mnc = ""; 561 String imsi = ""; 562 String gid1 = ""; 563 String gid2 = ""; 564 String spn = TelephonyManager.from(mContext).getSimOperatorNameForPhone(phoneId); 565 String simOperator = TelephonyManager.from(mContext).getSimOperatorNumericForPhone(phoneId); 566 // A valid simOperator should be 5 or 6 digits, depending on the length of the MNC. 567 if (simOperator != null && simOperator.length() >= 3) { 568 mcc = simOperator.substring(0, 3); 569 mnc = simOperator.substring(3); 570 } 571 Phone phone = PhoneFactory.getPhone(phoneId); 572 if (phone != null) { 573 imsi = phone.getSubscriberId(); 574 gid1 = phone.getGroupIdLevel1(); 575 gid2 = phone.getGroupIdLevel2(); 576 } 577 578 return new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2); 579 } 580 581 /** Returns the package name of a priveleged carrier app, or null if there is none. */ getCarrierPackageForPhoneId(int phoneId)582 private String getCarrierPackageForPhoneId(int phoneId) { 583 List<String> carrierPackageNames = TelephonyManager.from(mContext) 584 .getCarrierPackageNamesForIntentAndPhone( 585 new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId); 586 if (carrierPackageNames != null && carrierPackageNames.size() > 0) { 587 return carrierPackageNames.get(0); 588 } else { 589 return null; 590 } 591 } 592 getIccIdForPhoneId(int phoneId)593 private String getIccIdForPhoneId(int phoneId) { 594 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 595 return null; 596 } 597 Phone phone = PhoneFactory.getPhone(phoneId); 598 if (phone == null) { 599 return null; 600 } 601 return phone.getIccSerialNumber(); 602 } 603 604 /** 605 * Writes a bundle to an XML file. 606 * 607 * The bundle will be written to a file named after the package name and ICCID, so that it can 608 * be restored later with {@link @restoreConfigFromXml}. The XML output will include the bundle 609 * and the current version of the specified package. 610 * 611 * In case of errors or invalid input, no file will be written. 612 * 613 * @param packageName the name of the package from which we fetched this bundle. 614 * @param iccid the ICCID of the subscription for which this bundle was fetched. 615 * @param config the bundle to be written. Null will be treated as an empty bundle. 616 */ saveConfigToXml(String packageName, String iccid, PersistableBundle config)617 private void saveConfigToXml(String packageName, String iccid, PersistableBundle config) { 618 if (packageName == null || iccid == null) { 619 loge("Cannot save config with null packageName or iccid."); 620 return; 621 } 622 // b/32668103 Only save to file if config isn't empty. 623 // In case of failure, not caching an empty bundle will 624 // try loading config again on next power on or sim loaded. 625 // Downside is for genuinely empty bundle, will bind and load 626 // on every power on. 627 if (config == null || config.isEmpty()) { 628 return; 629 } 630 631 final String version = getPackageVersion(packageName); 632 if (version == null) { 633 loge("Failed to get package version for: " + packageName); 634 return; 635 } 636 637 FileOutputStream outFile = null; 638 try { 639 outFile = new FileOutputStream( 640 new File(mContext.getFilesDir(), getFilenameForConfig(packageName, iccid))); 641 FastXmlSerializer out = new FastXmlSerializer(); 642 out.setOutput(outFile, "utf-8"); 643 out.startDocument("utf-8", true); 644 out.startTag(null, TAG_DOCUMENT); 645 out.startTag(null, TAG_VERSION); 646 out.text(version); 647 out.endTag(null, TAG_VERSION); 648 out.startTag(null, TAG_BUNDLE); 649 config.saveToXml(out); 650 out.endTag(null, TAG_BUNDLE); 651 out.endTag(null, TAG_DOCUMENT); 652 out.endDocument(); 653 out.flush(); 654 outFile.close(); 655 } 656 catch (IOException e) { 657 loge(e.toString()); 658 } 659 catch (XmlPullParserException e) { 660 loge(e.toString()); 661 } 662 } 663 664 /** 665 * Reads a bundle from an XML file. 666 * 667 * This restores a bundle that was written with {@link #saveConfigToXml}. This returns the saved 668 * config bundle for the given package and ICCID. 669 * 670 * In case of errors, or if the saved config is from a different package version than the 671 * current version, then null will be returned. 672 * 673 * @param packageName the name of the package from which we fetched this bundle. 674 * @param iccid the ICCID of the subscription for which this bundle was fetched. 675 * @return the bundle from the XML file. Returns null if there is no saved config, the saved 676 * version does not match, or reading config fails. 677 */ restoreConfigFromXml(String packageName, String iccid)678 private PersistableBundle restoreConfigFromXml(String packageName, String iccid) { 679 final String version = getPackageVersion(packageName); 680 if (version == null) { 681 loge("Failed to get package version for: " + packageName); 682 return null; 683 } 684 if (packageName == null || iccid == null) { 685 loge("Cannot restore config with null packageName or iccid."); 686 return null; 687 } 688 689 PersistableBundle restoredBundle = null; 690 FileInputStream inFile = null; 691 try { 692 inFile = new FileInputStream( 693 new File(mContext.getFilesDir(), getFilenameForConfig(packageName, iccid))); 694 XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); 695 parser.setInput(inFile, "utf-8"); 696 697 int event; 698 while (((event = parser.next()) != XmlPullParser.END_DOCUMENT)) { 699 700 if (event == XmlPullParser.START_TAG && TAG_VERSION.equals(parser.getName())) { 701 String savedVersion = parser.nextText(); 702 if (!version.equals(savedVersion)) { 703 log("Saved version mismatch: " + version + " vs " + savedVersion); 704 break; 705 } 706 } 707 708 if (event == XmlPullParser.START_TAG && TAG_BUNDLE.equals(parser.getName())) { 709 restoredBundle = PersistableBundle.restoreFromXml(parser); 710 } 711 } 712 inFile.close(); 713 } 714 catch (FileNotFoundException e) { 715 loge(e.toString()); 716 } 717 catch (XmlPullParserException e) { 718 loge(e.toString()); 719 } 720 catch (IOException e) { 721 loge(e.toString()); 722 } 723 724 return restoredBundle; 725 } 726 727 /** 728 * Clears cached carrier config. 729 * This deletes all saved XML files associated with the given package name. If packageName is 730 * null, then it deletes all saved XML files. 731 * 732 * @param packageName the name of a carrier package, or null if all cached config should be 733 * cleared. 734 * @return true iff one or more files were deleted. 735 */ clearCachedConfigForPackage(final String packageName)736 private boolean clearCachedConfigForPackage(final String packageName) { 737 File dir = mContext.getFilesDir(); 738 File[] packageFiles = dir.listFiles(new FilenameFilter() { 739 public boolean accept(File dir, String filename) { 740 if (packageName != null) { 741 return filename.startsWith("carrierconfig-" + packageName + "-"); 742 } else { 743 return filename.startsWith("carrierconfig-"); 744 } 745 } 746 }); 747 if (packageFiles == null || packageFiles.length < 1) return false; 748 for (File f : packageFiles) { 749 log("deleting " + f.getName()); 750 f.delete(); 751 } 752 return true; 753 } 754 755 /** Builds a canonical file name for a config file. */ getFilenameForConfig(@onNull String packageName, @NonNull String iccid)756 private String getFilenameForConfig(@NonNull String packageName, @NonNull String iccid) { 757 return "carrierconfig-" + packageName + "-" + iccid + ".xml"; 758 } 759 760 /** Return the current version code of a package, or null if the name is not found. */ getPackageVersion(String packageName)761 private String getPackageVersion(String packageName) { 762 try { 763 PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0); 764 return Long.toString(info.getLongVersionCode()); 765 } catch (PackageManager.NameNotFoundException e) { 766 return null; 767 } 768 } 769 770 /** 771 * Read up to date config. 772 * 773 * This reads config bundles for the given phoneId. That means getting the latest bundle from 774 * the default app and a privileged carrier app, if present. This will not bind to an app if we 775 * have a saved config file to use instead. 776 */ updateConfigForPhoneId(int phoneId)777 private void updateConfigForPhoneId(int phoneId) { 778 // Clear in-memory cache for carrier app config, so when carrier app gets uninstalled, no 779 // stale config is left. 780 if (mConfigFromCarrierApp[phoneId] != null && 781 getCarrierPackageForPhoneId(phoneId) == null) { 782 mConfigFromCarrierApp[phoneId] = null; 783 } 784 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DO_FETCH_DEFAULT, phoneId, -1)); 785 } 786 787 @Override public 788 @NonNull getConfigForSubId(int subId)789 PersistableBundle getConfigForSubId(int subId) { 790 // TODO(b/73136824): Migrate to TelephonyPermissions#checkCallingOrSelfReadPhoneState. 791 try { 792 mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, null); 793 // SKIP checking run-time READ_PHONE_STATE since using PRIVILEGED 794 } catch (SecurityException e) { 795 try { 796 mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null); 797 } catch (SecurityException securityException) { 798 // If we don't have the runtime permission, but do have carrier privileges, that 799 // suffices for reading phone state. 800 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 801 throw securityException; 802 } 803 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, null); 804 } 805 } 806 807 int phoneId = SubscriptionManager.getPhoneId(subId); 808 PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig(); 809 if (SubscriptionManager.isValidPhoneId(phoneId)) { 810 PersistableBundle config = mConfigFromDefaultApp[phoneId]; 811 if (config != null) { 812 retConfig.putAll(config); 813 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); 814 } 815 config = mConfigFromCarrierApp[phoneId]; 816 if (config != null) { 817 retConfig.putAll(config); 818 retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true); 819 } 820 } 821 return retConfig; 822 } 823 824 @Override notifyConfigChangedForSubId(int subId)825 public void notifyConfigChangedForSubId(int subId) { 826 int phoneId = SubscriptionManager.getPhoneId(subId); 827 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 828 log("Ignore invalid phoneId: " + phoneId + " for subId: " + subId); 829 return; 830 } 831 String callingPackageName = mContext.getPackageManager().getNameForUid( 832 Binder.getCallingUid()); 833 // TODO: Check that the calling packages is privileged for subId specifically. 834 int privilegeStatus = TelephonyManager.from(mContext).checkCarrierPrivilegesForPackage( 835 callingPackageName); 836 // Requires the calling app to be either a carrier privileged app or 837 // system privileged app with MODIFY_PHONE_STATE permission. 838 if (privilegeStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 839 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, 840 "Require carrier privileges or MODIFY_PHONE_STATE permission."); 841 } 842 843 // This method should block until deleting has completed, so that an error which prevents us 844 // from clearing the cache is passed back to the carrier app. With the files successfully 845 // deleted, this can return and we will eventually bind to the carrier app. 846 clearCachedConfigForPackage(callingPackageName); 847 updateConfigForPhoneId(phoneId); 848 } 849 850 @Override updateConfigForPhoneId(int phoneId, String simState)851 public void updateConfigForPhoneId(int phoneId, String simState) { 852 mContext.enforceCallingOrSelfPermission( 853 android.Manifest.permission.MODIFY_PHONE_STATE, null); 854 log("update config for phoneId: " + phoneId + " simState: " + simState); 855 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 856 return; 857 } 858 // requires Java 7 for switch on string. 859 switch (simState) { 860 case IccCardConstants.INTENT_VALUE_ICC_ABSENT: 861 case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR: 862 case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED: 863 case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN: 864 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_CONFIG, phoneId, -1)); 865 break; 866 case IccCardConstants.INTENT_VALUE_ICC_LOADED: 867 case IccCardConstants.INTENT_VALUE_ICC_LOCKED: 868 updateConfigForPhoneId(phoneId); 869 break; 870 } 871 } 872 873 @Override getDefaultCarrierServicePackageName()874 public String getDefaultCarrierServicePackageName() { 875 return mPlatformCarrierConfigPackage; 876 } 877 878 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)879 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 880 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 881 != PackageManager.PERMISSION_GRANTED) { 882 pw.println("Permission Denial: can't dump carrierconfig from from pid=" 883 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 884 return; 885 } 886 pw.println("CarrierConfigLoader: " + this); 887 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) { 888 pw.println("Phone Id = " + i); 889 // display default values in CarrierConfigManager 890 printConfig(CarrierConfigManager.getDefaultConfig(), pw, 891 "Default Values from CarrierConfigManager"); 892 pw.println(""); 893 // display ConfigFromDefaultApp 894 printConfig(mConfigFromDefaultApp[i], pw, "mConfigFromDefaultApp"); 895 pw.println(""); 896 // display ConfigFromCarrierApp 897 printConfig(mConfigFromCarrierApp[i], pw, "mConfigFromCarrierApp"); 898 } 899 } 900 printConfig(PersistableBundle configApp, PrintWriter pw, String name)901 private void printConfig(PersistableBundle configApp, PrintWriter pw, String name) { 902 IndentingPrintWriter indentPW = new IndentingPrintWriter(pw, " "); 903 if (configApp == null) { 904 indentPW.increaseIndent(); 905 indentPW.println(name + " : null "); 906 return; 907 } 908 indentPW.increaseIndent(); 909 indentPW.println(name + " : "); 910 List<String> sortedKeys = new ArrayList<String>(configApp.keySet()); 911 Collections.sort(sortedKeys); 912 indentPW.increaseIndent(); 913 indentPW.increaseIndent(); 914 for (String key : sortedKeys) { 915 if (configApp.get(key) != null && configApp.get(key) instanceof Object[]) { 916 indentPW.println(key + " = " + 917 Arrays.toString((Object[]) configApp.get(key))); 918 } else if (configApp.get(key) != null && configApp.get(key) instanceof int[]) { 919 indentPW.println(key + " = " + Arrays.toString((int[]) configApp.get(key))); 920 } else { 921 indentPW.println(key + " = " + configApp.get(key)); 922 } 923 } 924 } 925 926 private class CarrierServiceConnection implements ServiceConnection { 927 int phoneId; 928 int eventId; 929 IBinder service; 930 CarrierServiceConnection(int phoneId, int eventId)931 public CarrierServiceConnection(int phoneId, int eventId) { 932 this.phoneId = phoneId; 933 this.eventId = eventId; 934 } 935 936 @Override onServiceConnected(ComponentName name, IBinder service)937 public void onServiceConnected(ComponentName name, IBinder service) { 938 log("Connected to config app: " + name.flattenToString()); 939 this.service = service; 940 mHandler.sendMessage(mHandler.obtainMessage(eventId, phoneId, -1, this)); 941 } 942 943 @Override onServiceDisconnected(ComponentName name)944 public void onServiceDisconnected(ComponentName name) { 945 this.service = null; 946 } 947 } 948 949 private class ConfigLoaderBroadcastReceiver extends BroadcastReceiver { 950 @Override onReceive(Context context, Intent intent)951 public void onReceive(Context context, Intent intent) { 952 String action = intent.getAction(); 953 boolean replace = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); 954 // If replace is true, only care ACTION_PACKAGE_REPLACED. 955 if (replace && !Intent.ACTION_PACKAGE_REPLACED.equals(action)) 956 return; 957 958 switch (action) { 959 case Intent.ACTION_BOOT_COMPLETED: 960 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_UNLOCKED, null)); 961 break; 962 963 case Intent.ACTION_PACKAGE_ADDED: 964 case Intent.ACTION_PACKAGE_REMOVED: 965 case Intent.ACTION_PACKAGE_REPLACED: 966 int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 967 String packageName = mContext.getPackageManager().getNameForUid(uid); 968 if (packageName != null) { 969 // We don't have a phoneId for arg1. 970 mHandler.sendMessage( 971 mHandler.obtainMessage(EVENT_PACKAGE_CHANGED, packageName)); 972 } 973 break; 974 } 975 } 976 } 977 log(String msg)978 private static void log(String msg) { 979 Log.d(LOG_TAG, msg); 980 } 981 loge(String msg)982 private static void loge(String msg) { 983 Log.e(LOG_TAG, msg); 984 } 985 } 986