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