1 /* 2 * Copyright (C) 2006 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.internal.telephony; 18 19 import static android.telephony.TelephonyManager.HAL_SERVICE_RADIO; 20 21 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA; 22 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA_LTE; 23 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM; 24 25 import static java.util.Arrays.copyOf; 26 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.compat.annotation.UnsupportedAppUsage; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.SharedPreferences; 33 import android.content.pm.PackageManager; 34 import android.net.LocalServerSocket; 35 import android.os.Build; 36 import android.os.Looper; 37 import android.preference.PreferenceManager; 38 import android.provider.Settings; 39 import android.provider.Settings.SettingNotFoundException; 40 import android.telephony.AnomalyReporter; 41 import android.telephony.RadioAccessFamily; 42 import android.telephony.SubscriptionManager; 43 import android.telephony.TelephonyManager; 44 import android.util.LocalLog; 45 46 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 47 import com.android.internal.telephony.data.CellularNetworkValidator; 48 import com.android.internal.telephony.data.PhoneSwitcher; 49 import com.android.internal.telephony.data.TelephonyNetworkProvider; 50 import com.android.internal.telephony.euicc.EuiccCardController; 51 import com.android.internal.telephony.euicc.EuiccController; 52 import com.android.internal.telephony.flags.FeatureFlags; 53 import com.android.internal.telephony.flags.FeatureFlagsImpl; 54 import com.android.internal.telephony.imsphone.ImsPhone; 55 import com.android.internal.telephony.imsphone.ImsPhoneFactory; 56 import com.android.internal.telephony.metrics.MetricsCollector; 57 import com.android.internal.telephony.metrics.TelephonyMetrics; 58 import com.android.internal.telephony.subscription.SubscriptionManagerService; 59 import com.android.internal.telephony.uicc.UiccController; 60 import com.android.internal.telephony.util.NotificationChannelController; 61 import com.android.internal.util.IndentingPrintWriter; 62 import com.android.telephony.Rlog; 63 64 import java.io.FileDescriptor; 65 import java.io.PrintWriter; 66 import java.lang.reflect.Method; 67 import java.util.HashMap; 68 import java.util.Map; 69 70 /** 71 * {@hide} 72 */ 73 public class PhoneFactory { 74 static final String LOG_TAG = "PhoneFactory"; 75 static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000; 76 static final int SOCKET_OPEN_MAX_RETRY = 3; 77 static final boolean DBG = false; 78 79 //***** Class Variables 80 81 // lock sLockProxyPhones protects sPhones, sPhone 82 final static Object sLockProxyPhones = new Object(); 83 static private Phone[] sPhones = null; 84 static private Phone sPhone = null; 85 86 static private CommandsInterface[] sCommandsInterfaces = null; 87 88 static private ProxyController sProxyController; 89 static private UiccController sUiccController; 90 private static IntentBroadcaster sIntentBroadcaster; 91 private static @Nullable EuiccController sEuiccController; 92 private static @Nullable EuiccCardController sEuiccCardController; 93 private static SubscriptionManagerService sSubscriptionManagerService; 94 95 @UnsupportedAppUsage 96 static private boolean sMadeDefaults = false; 97 @UnsupportedAppUsage 98 static private PhoneNotifier sPhoneNotifier; 99 @UnsupportedAppUsage 100 static private Context sContext; 101 static private PhoneConfigurationManager sPhoneConfigurationManager; 102 static private SimultaneousCallingTracker sSimultaneousCallingTracker; 103 static private PhoneSwitcher sPhoneSwitcher; 104 private static TelephonyNetworkProvider sTelephonyNetworkProvider; 105 static private NotificationChannelController sNotificationChannelController; 106 static private CellularNetworkValidator sCellularNetworkValidator; 107 108 static private final HashMap<String, LocalLog>sLocalLogs = new HashMap<String, LocalLog>(); 109 private static MetricsCollector sMetricsCollector; 110 private static RadioInterfaceCapabilityController sRadioHalCapabilities; 111 private static @NonNull FeatureFlags sFeatureFlags = new FeatureFlagsImpl(); 112 113 //***** Class Methods 114 115 /** 116 * @param context The context. 117 * @param featureFlags The feature flag. 118 */ makeDefaultPhones(Context context, @NonNull FeatureFlags featureFlags)119 public static void makeDefaultPhones(Context context, @NonNull FeatureFlags featureFlags) { 120 sFeatureFlags = featureFlags; 121 makeDefaultPhone(context, featureFlags); 122 } 123 124 /** 125 * FIXME replace this with some other way of making these 126 * instances 127 */ 128 @UnsupportedAppUsage makeDefaultPhone(Context context, @NonNull FeatureFlags featureFlags)129 public static void makeDefaultPhone(Context context, @NonNull FeatureFlags featureFlags) { 130 synchronized (sLockProxyPhones) { 131 if (!sMadeDefaults) { 132 sContext = context; 133 134 // create the telephony device controller. 135 TelephonyDevController.create(); 136 137 TelephonyMetrics metrics = TelephonyMetrics.getInstance(); 138 metrics.setContext(context); 139 140 int retryCount = 0; 141 for(;;) { 142 boolean hasException = false; 143 retryCount ++; 144 145 try { 146 // use UNIX domain socket to 147 // prevent subsequent initialization 148 new LocalServerSocket("com.android.internal.telephony"); 149 } catch (java.io.IOException ex) { 150 hasException = true; 151 } 152 153 if ( !hasException ) { 154 break; 155 } else if (retryCount > SOCKET_OPEN_MAX_RETRY) { 156 throw new RuntimeException("PhoneFactory probably already running"); 157 } else { 158 try { 159 Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); 160 } catch (InterruptedException er) { 161 } 162 } 163 } 164 165 // register statsd pullers. 166 sMetricsCollector = new MetricsCollector(context, sFeatureFlags); 167 168 sPhoneNotifier = new DefaultPhoneNotifier(context, featureFlags); 169 170 int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context); 171 Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription); 172 173 /* In case of multi SIM mode two instances of Phone, RIL are created, 174 where as in single SIM mode only instance. isMultiSimEnabled() function checks 175 whether it is single SIM or multi SIM mode */ 176 int numPhones = TelephonyManager.getDefault().getActiveModemCount(); 177 178 int[] networkModes = new int[numPhones]; 179 sPhones = new Phone[numPhones]; 180 sCommandsInterfaces = new RIL[numPhones]; 181 182 for (int i = 0; i < numPhones; i++) { 183 // reads the system properties and makes commandsinterface 184 // Get preferred network type. 185 networkModes[i] = RILConstants.PREFERRED_NETWORK_MODE; 186 187 Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i])); 188 sCommandsInterfaces[i] = new RIL(context, 189 RadioAccessFamily.getRafFromNetworkType(networkModes[i]), 190 cdmaSubscription, i, featureFlags); 191 } 192 193 if (numPhones > 0) { 194 final RadioConfig radioConfig = RadioConfig.make(context, 195 sCommandsInterfaces[0].getHalVersion(HAL_SERVICE_RADIO)); 196 sRadioHalCapabilities = RadioInterfaceCapabilityController.init(radioConfig, 197 sCommandsInterfaces[0]); 198 } else { 199 // There is no command interface to go off of 200 final RadioConfig radioConfig = RadioConfig.make(context, HalVersion.UNKNOWN); 201 sRadioHalCapabilities = RadioInterfaceCapabilityController.init( 202 radioConfig, null); 203 } 204 205 206 // Instantiate UiccController so that all other classes can just 207 // call getInstance() 208 sUiccController = UiccController.make(context, featureFlags); 209 210 Rlog.i(LOG_TAG, "Creating SubscriptionManagerService"); 211 sSubscriptionManagerService = new SubscriptionManagerService(context, 212 Looper.myLooper(), featureFlags); 213 214 TelephonyComponentFactory.getInstance().inject(MultiSimSettingController.class. 215 getName()).initMultiSimSettingController(context, featureFlags); 216 217 if (context.getPackageManager().hasSystemFeature( 218 PackageManager.FEATURE_TELEPHONY_EUICC)) { 219 sEuiccController = EuiccController.init(context, sFeatureFlags); 220 sEuiccCardController = EuiccCardController.init(context, sFeatureFlags); 221 } 222 223 for (int i = 0; i < numPhones; i++) { 224 sPhones[i] = createPhone(context, i); 225 } 226 227 // Set the default phone in base class. 228 // FIXME: This is a first best guess at what the defaults will be. It 229 // FIXME: needs to be done in a more controlled manner in the future. 230 if (numPhones > 0) sPhone = sPhones[0]; 231 232 // Ensure that we have a default SMS app. Requesting the app with 233 // updateIfNeeded set to true is enough to configure a default SMS app. 234 ComponentName componentName = 235 SmsApplication.getDefaultSmsApplication(context, true /* updateIfNeeded */); 236 String packageName = "NONE"; 237 if (componentName != null) { 238 packageName = componentName.getPackageName(); 239 } 240 Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName); 241 242 if (sFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) { 243 // Explicitly call this, even if the user has no default Sms application, to 244 // ensure that the System apps have the appropriate permissions. 245 SmsApplication.grantPermissionsToSystemApps(context); 246 } 247 248 // Set up monitor to watch for changes to SMS packages 249 SmsApplication.initSmsPackageMonitor(context); 250 251 sMadeDefaults = true; 252 253 // Only bring up IMS if the device supports having an IMS stack. 254 if (context.getPackageManager().hasSystemFeature( 255 PackageManager.FEATURE_TELEPHONY_IMS)) { 256 // Start monitoring after defaults have been made. 257 // Default phone must be ready before ImsPhone is created because ImsService 258 // might need it when it is being opened. 259 for (int i = 0; i < numPhones; i++) { 260 sPhones[i].createImsPhone(); 261 } 262 } else { 263 Rlog.i(LOG_TAG, "IMS is not supported on this device, skipping ImsResolver."); 264 } 265 266 sPhoneConfigurationManager = PhoneConfigurationManager.init(sContext, featureFlags); 267 if (featureFlags.simultaneousCallingIndications()) { 268 sSimultaneousCallingTracker = 269 SimultaneousCallingTracker.init(sContext, featureFlags); 270 } 271 272 sCellularNetworkValidator = CellularNetworkValidator.make(sContext, sFeatureFlags); 273 274 int maxActivePhones = sPhoneConfigurationManager 275 .getNumberOfModemsWithSimultaneousDataConnections(); 276 277 sPhoneSwitcher = TelephonyComponentFactory.getInstance().inject( 278 PhoneSwitcher.class.getName()). 279 makePhoneSwitcher(maxActivePhones, sContext, Looper.myLooper(), 280 featureFlags); 281 282 sProxyController = ProxyController.getInstance(context, featureFlags); 283 284 sIntentBroadcaster = IntentBroadcaster.getInstance(context); 285 286 sNotificationChannelController = new NotificationChannelController(context); 287 288 // Create the TelephonyNetworkProvider instance, which is a singleton. 289 sTelephonyNetworkProvider = new TelephonyNetworkProvider(Looper.myLooper(), 290 context, featureFlags); 291 } 292 } 293 } 294 295 /** 296 * Upon single SIM to dual SIM switch or vice versa, we dynamically allocate or de-allocate 297 * Phone and CommandInterface objects. 298 * 299 * @param context The context 300 * @param activeModemCount The number of active modems 301 */ onMultiSimConfigChanged(Context context, int activeModemCount)302 public static void onMultiSimConfigChanged(Context context, int activeModemCount) { 303 synchronized (sLockProxyPhones) { 304 int prevActiveModemCount = sPhones.length; 305 if (prevActiveModemCount == activeModemCount) return; 306 307 // Currently we will not clean up the 2nd Phone object, so that it can be re-used if 308 // user switches back. 309 if (prevActiveModemCount > activeModemCount) return; 310 311 sPhones = copyOf(sPhones, activeModemCount); 312 sCommandsInterfaces = copyOf(sCommandsInterfaces, activeModemCount); 313 314 int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context); 315 for (int i = prevActiveModemCount; i < activeModemCount; i++) { 316 sCommandsInterfaces[i] = new RIL(context, RadioAccessFamily.getRafFromNetworkType( 317 RILConstants.PREFERRED_NETWORK_MODE), 318 cdmaSubscription, i, sFeatureFlags); 319 sPhones[i] = createPhone(context, i); 320 if (context.getPackageManager().hasSystemFeature( 321 PackageManager.FEATURE_TELEPHONY_IMS)) { 322 sPhones[i].createImsPhone(); 323 } 324 } 325 } 326 } 327 createPhone(Context context, int phoneId)328 private static Phone createPhone(Context context, int phoneId) { 329 int phoneType; 330 if (sFeatureFlags.phoneTypeCleanup()) { 331 phoneType = PHONE_TYPE_GSM; 332 } else { 333 phoneType = TelephonyManager.getPhoneType(RILConstants.PREFERRED_NETWORK_MODE); 334 // We always use PHONE_TYPE_CDMA_LTE now. 335 if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE; 336 } 337 338 Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " phoneId = " + phoneId); 339 340 TelephonyComponentFactory injectedComponentFactory = 341 TelephonyComponentFactory.getInstance().inject(GsmCdmaPhone.class.getName()); 342 343 return injectedComponentFactory.makePhone(context, 344 sCommandsInterfaces[phoneId], sPhoneNotifier, phoneId, phoneType, 345 TelephonyComponentFactory.getInstance(), sFeatureFlags); 346 } 347 348 @UnsupportedAppUsage getDefaultPhone()349 public static Phone getDefaultPhone() { 350 synchronized (sLockProxyPhones) { 351 if (!sMadeDefaults) { 352 throw new IllegalStateException("Default phones haven't been made yet!"); 353 } 354 return sPhone; 355 } 356 } 357 358 @UnsupportedAppUsage getPhone(int phoneId)359 public static Phone getPhone(int phoneId) { 360 Phone phone; 361 String dbgInfo = ""; 362 363 synchronized (sLockProxyPhones) { 364 if (!sMadeDefaults) { 365 throw new IllegalStateException("Default phones haven't been made yet!"); 366 // CAF_MSIM FIXME need to introduce default phone id ? 367 } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) { 368 if (DBG) { 369 dbgInfo = "phoneId == DEFAULT_PHONE_ID return sPhone"; 370 } 371 phone = sPhone; 372 } else { 373 if (DBG) { 374 dbgInfo = "phoneId != DEFAULT_PHONE_ID return sPhones[phoneId]"; 375 } 376 phone = (phoneId >= 0 && phoneId < sPhones.length) 377 ? sPhones[phoneId] : null; 378 } 379 if (DBG) { 380 Rlog.d(LOG_TAG, "getPhone:- " + dbgInfo + " phoneId=" + phoneId + 381 " phone=" + phone); 382 } 383 return phone; 384 } 385 } 386 387 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getPhones()388 public static Phone[] getPhones() { 389 synchronized (sLockProxyPhones) { 390 if (!sMadeDefaults) { 391 throw new IllegalStateException("Default phones haven't been made yet!"); 392 } 393 return sPhones; 394 } 395 } 396 getNetworkProvider()397 public static TelephonyNetworkProvider getNetworkProvider() { 398 return sTelephonyNetworkProvider; 399 } 400 401 /** 402 * Returns the preferred network type bitmask that should be set in the modem. 403 * 404 * @param phoneId The phone's id. 405 * @return the preferred network mode bitmask that should be set. 406 */ 407 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) calculatePreferredNetworkType(int phoneId)408 public static int calculatePreferredNetworkType(int phoneId) { 409 if (getPhone(phoneId) == null) { 410 Rlog.d(LOG_TAG, "Invalid phoneId return default network mode "); 411 return RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE); 412 } 413 int networkType = (int) getPhone(phoneId).getAllowedNetworkTypes( 414 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER); 415 Rlog.d(LOG_TAG, "calculatePreferredNetworkType: phoneId = " + phoneId + " networkType = " 416 + networkType); 417 return networkType; 418 } 419 420 /* Gets the default subscription */ 421 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getDefaultSubscription()422 public static int getDefaultSubscription() { 423 return SubscriptionManagerService.getInstance().getDefaultSubId(); 424 } 425 426 /* Returns User SMS Prompt property, enabled or not */ isSMSPromptEnabled()427 public static boolean isSMSPromptEnabled() { 428 boolean prompt = false; 429 int value = 0; 430 try { 431 value = Settings.Global.getInt(sContext.getContentResolver(), 432 Settings.Global.MULTI_SIM_SMS_PROMPT); 433 } catch (SettingNotFoundException snfe) { 434 Rlog.e(LOG_TAG, "Settings Exception Reading Dual Sim SMS Prompt Values"); 435 } 436 prompt = (value == 0) ? false : true ; 437 Rlog.d(LOG_TAG, "SMS Prompt option:" + prompt); 438 439 return prompt; 440 } 441 442 /** 443 * Makes a {@link ImsPhone} object. 444 * @return the {@code ImsPhone} object or null if the exception occured 445 */ makeImsPhone(PhoneNotifier phoneNotifier, Phone defaultPhone)446 public static Phone makeImsPhone(PhoneNotifier phoneNotifier, Phone defaultPhone) { 447 return ImsPhoneFactory.makePhone(sContext, phoneNotifier, defaultPhone, sFeatureFlags); 448 } 449 450 /** 451 * Get the instance of {@link SmsController}. 452 */ getSmsController()453 public static SmsController getSmsController() { 454 synchronized (sLockProxyPhones) { 455 if (!sMadeDefaults) { 456 throw new IllegalStateException("Default phones haven't been made yet!"); 457 } 458 return sProxyController.getSmsController(); 459 } 460 } 461 462 /** 463 * Get Command Interfaces. 464 */ getCommandsInterfaces()465 public static CommandsInterface[] getCommandsInterfaces() { 466 synchronized (sLockProxyPhones) { 467 return sCommandsInterfaces; 468 } 469 } 470 471 /** 472 * Adds a local log category. 473 * 474 * Only used within the telephony process. Use localLog to add log entries. 475 * 476 * TODO - is there a better way to do this? Think about design when we have a minute. 477 * 478 * @param key the name of the category - will be the header in the service dump. 479 * @param size the number of lines to maintain in this category 480 */ addLocalLog(String key, int size)481 public static void addLocalLog(String key, int size) { 482 synchronized(sLocalLogs) { 483 if (sLocalLogs.containsKey(key)) { 484 throw new IllegalArgumentException("key " + key + " already present"); 485 } 486 sLocalLogs.put(key, new LocalLog(size)); 487 } 488 } 489 490 /** 491 * Add a line to the named Local Log. 492 * 493 * This will appear in the TelephonyDebugService dump. 494 * 495 * @param key the name of the log category to put this in. Must be created 496 * via addLocalLog. 497 * @param log the string to add to the log. 498 */ localLog(String key, String log)499 public static void localLog(String key, String log) { 500 synchronized(sLocalLogs) { 501 if (sLocalLogs.containsKey(key) == false) { 502 throw new IllegalArgumentException("key " + key + " not found"); 503 } 504 sLocalLogs.get(key).log(log); 505 } 506 } 507 508 /** Returns the MetricsCollector instance. */ getMetricsCollector()509 public static MetricsCollector getMetricsCollector() { 510 return sMetricsCollector; 511 } 512 513 /** 514 * Print all feature flag configurations that Telephony is using for debugging purposes. 515 */ reflectAndPrintFlagConfigs(IndentingPrintWriter pw)516 private static void reflectAndPrintFlagConfigs(IndentingPrintWriter pw) { 517 518 try { 519 // Look away, a forbidden technique (reflection) is being used to allow us to get 520 // all flag configs without having to add them manually to this method. 521 Method[] methods = FeatureFlags.class.getMethods(); 522 if (methods.length == 0) { 523 pw.println("NONE"); 524 return; 525 } 526 for (Method m : methods) { 527 pw.println(m.getName() + "-> " + m.invoke(sFeatureFlags)); 528 } 529 } catch (Exception e) { 530 pw.println("[ERROR]"); 531 } 532 } 533 dump(FileDescriptor fd, PrintWriter printwriter, String[] args)534 public static void dump(FileDescriptor fd, PrintWriter printwriter, String[] args) { 535 IndentingPrintWriter pw = new IndentingPrintWriter(printwriter, " "); 536 pw.println("PhoneFactory:"); 537 pw.println(" sMadeDefaults=" + sMadeDefaults); 538 539 sPhoneSwitcher.dump(fd, pw, args); 540 pw.println(); 541 542 Phone[] phones = (Phone[])PhoneFactory.getPhones(); 543 for (int i = 0; i < phones.length; i++) { 544 pw.increaseIndent(); 545 Phone phone = phones[i]; 546 547 try { 548 phone.dump(fd, pw, args); 549 } catch (Exception e) { 550 pw.println("Telephony DebugService: Could not get Phone[" + i + "] e=" + e); 551 continue; 552 } 553 554 pw.flush(); 555 pw.println("++++++++++++++++++++++++++++++++"); 556 } 557 558 pw.increaseIndent(); 559 sTelephonyNetworkProvider.dump(fd, pw, args); 560 pw.decreaseIndent(); 561 pw.println("++++++++++++++++++++++++++++++++"); 562 563 pw.println("UiccController:"); 564 pw.increaseIndent(); 565 try { 566 sUiccController.dump(fd, pw, args); 567 } catch (Exception e) { 568 e.printStackTrace(); 569 } 570 pw.flush(); 571 pw.decreaseIndent(); 572 pw.println("++++++++++++++++++++++++++++++++"); 573 574 pw.flush(); 575 pw.decreaseIndent(); 576 pw.println("++++++++++++++++++++++++++++++++"); 577 578 pw.println("sRadioHalCapabilities:"); 579 pw.increaseIndent(); 580 try { 581 sRadioHalCapabilities.dump(fd, pw, args); 582 } catch (Exception e) { 583 e.printStackTrace(); 584 } 585 pw.flush(); 586 pw.decreaseIndent(); 587 pw.println("++++++++++++++++++++++++++++++++"); 588 589 pw.println("LocalLogs:"); 590 pw.increaseIndent(); 591 synchronized (sLocalLogs) { 592 for (String key : sLocalLogs.keySet()) { 593 pw.println(key); 594 pw.increaseIndent(); 595 sLocalLogs.get(key).dump(fd, pw, args); 596 pw.decreaseIndent(); 597 } 598 pw.flush(); 599 } 600 pw.decreaseIndent(); 601 pw.println("++++++++++++++++++++++++++++++++"); 602 603 pw.println("SharedPreferences:"); 604 pw.increaseIndent(); 605 try { 606 if (sContext != null) { 607 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(sContext); 608 Map spValues = sp.getAll(); 609 for (Object key : spValues.keySet()) { 610 pw.println(key + " : " + spValues.get(key)); 611 } 612 } 613 } catch (Exception e) { 614 e.printStackTrace(); 615 } 616 pw.decreaseIndent(); 617 pw.println("++++++++++++++++++++++++++++++++"); 618 pw.println("DebugEvents:"); 619 pw.increaseIndent(); 620 try { 621 AnomalyReporter.dump(fd, pw, args); 622 } catch (Exception e) { 623 e.printStackTrace(); 624 } 625 pw.flush(); 626 pw.decreaseIndent(); 627 628 pw.println("++++++++++++++++++++++++++++++++"); 629 pw.println("Flag Configurations:"); 630 pw.increaseIndent(); 631 reflectAndPrintFlagConfigs(pw); 632 pw.flush(); 633 pw.decreaseIndent(); 634 pw.println("++++++++++++++++++++++++++++++++"); 635 } 636 } 637