1 /* 2 * Copyright (C) 2016 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 android.app.Notification; 20 import android.app.NotificationManager; 21 import android.app.PendingIntent; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.res.Resources; 25 import android.os.Handler; 26 import android.os.HandlerExecutor; 27 import android.os.Message; 28 import android.os.PersistableBundle; 29 import android.provider.Settings; 30 import android.telephony.CarrierConfigManager; 31 import android.telephony.RadioAccessFamily; 32 import android.telephony.ServiceState; 33 import android.telephony.SubscriptionManager; 34 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 35 import android.telephony.TelephonyCallback; 36 import android.telephony.TelephonyManager; 37 import android.telephony.TelephonyManager.NetworkTypeBitMask; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.internal.telephony.util.ArrayUtils; 41 import com.android.internal.telephony.util.NotificationChannelController; 42 import com.android.telephony.Rlog; 43 44 import java.util.HashMap; 45 import java.util.Map; 46 47 /** 48 * This contains Carrier specific logic based on the states/events 49 * managed in ServiceStateTracker. 50 * {@hide} 51 */ 52 public class CarrierServiceStateTracker extends Handler { 53 private static final String LOG_TAG = "CSST"; 54 protected static final int CARRIER_EVENT_BASE = 100; 55 protected static final int CARRIER_EVENT_VOICE_REGISTRATION = CARRIER_EVENT_BASE + 1; 56 protected static final int CARRIER_EVENT_VOICE_DEREGISTRATION = CARRIER_EVENT_BASE + 2; 57 protected static final int CARRIER_EVENT_DATA_REGISTRATION = CARRIER_EVENT_BASE + 3; 58 protected static final int CARRIER_EVENT_DATA_DEREGISTRATION = CARRIER_EVENT_BASE + 4; 59 protected static final int CARRIER_EVENT_IMS_CAPABILITIES_CHANGED = CARRIER_EVENT_BASE + 5; 60 61 private static final int UNINITIALIZED_DELAY_VALUE = -1; 62 private Phone mPhone; 63 private ServiceStateTracker mSST; 64 private final Map<Integer, NotificationType> mNotificationTypeMap = new HashMap<>(); 65 private int mPreviousSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 66 public static final int NOTIFICATION_PREF_NETWORK = 1000; 67 public static final int NOTIFICATION_EMERGENCY_NETWORK = 1001; 68 69 @VisibleForTesting 70 public static final String EMERGENCY_NOTIFICATION_TAG = "EmergencyNetworkNotification"; 71 72 @VisibleForTesting 73 public static final String PREF_NETWORK_NOTIFICATION_TAG = "PrefNetworkNotification"; 74 75 private long mAllowedNetworkType = -1; 76 private AllowedNetworkTypesListener mAllowedNetworkTypesListener; 77 private TelephonyManager mTelephonyManager; 78 79 /** 80 * The listener for allowed network types changed 81 */ 82 @VisibleForTesting 83 public class AllowedNetworkTypesListener extends TelephonyCallback 84 implements TelephonyCallback.AllowedNetworkTypesListener { 85 @Override onAllowedNetworkTypesChanged(int reason, long newAllowedNetworkType)86 public void onAllowedNetworkTypesChanged(int reason, long newAllowedNetworkType) { 87 if (reason != TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER) { 88 return; 89 } 90 91 if (mAllowedNetworkType != newAllowedNetworkType) { 92 mAllowedNetworkType = newAllowedNetworkType; 93 handleAllowedNetworkTypeChanged(); 94 } 95 } 96 } 97 CarrierServiceStateTracker(Phone phone, ServiceStateTracker sst)98 public CarrierServiceStateTracker(Phone phone, ServiceStateTracker sst) { 99 this.mPhone = phone; 100 this.mSST = sst; 101 mTelephonyManager = mPhone.getContext().getSystemService( 102 TelephonyManager.class).createForSubscriptionId(mPhone.getSubId()); 103 CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class); 104 ccm.registerCarrierConfigChangeListener( 105 mPhone.getContext().getMainExecutor(), 106 (slotIndex, subId, carrierId, specificCarrierId) -> { 107 if (slotIndex != mPhone.getPhoneId()) return; 108 109 Rlog.d(LOG_TAG, "onCarrierConfigChanged: slotIndex=" + slotIndex 110 + ", subId=" + subId + ", carrierId=" + carrierId); 111 112 // Only get carrier configs used for EmergencyNetworkNotification 113 // and PrefNetworkNotification 114 PersistableBundle b = 115 CarrierConfigManager.getCarrierConfigSubset( 116 mPhone.getContext(), 117 mPhone.getSubId(), 118 CarrierConfigManager.KEY_EMERGENCY_NOTIFICATION_DELAY_INT, 119 CarrierConfigManager.KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, 120 CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL); 121 if (b.isEmpty()) return; 122 123 for (Map.Entry<Integer, NotificationType> entry : 124 mNotificationTypeMap.entrySet()) { 125 NotificationType notificationType = entry.getValue(); 126 notificationType.setDelay(b); 127 notificationType.setEnabled(b); 128 } 129 handleConfigChanges(); 130 }); 131 132 // Listen for subscriber changes 133 SubscriptionManager.from(mPhone.getContext()).addOnSubscriptionsChangedListener( 134 new OnSubscriptionsChangedListener(this.getLooper()) { 135 @Override 136 public void onSubscriptionsChanged() { 137 int subId = mPhone.getSubId(); 138 if (mPreviousSubId != subId) { 139 mPreviousSubId = subId; 140 mTelephonyManager = mTelephonyManager.createForSubscriptionId( 141 mPhone.getSubId()); 142 registerAllowedNetworkTypesListener(); 143 } 144 } 145 }); 146 147 registerNotificationTypes(); 148 mAllowedNetworkType = RadioAccessFamily.getNetworkTypeFromRaf( 149 (int) mPhone.getAllowedNetworkTypes( 150 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)); 151 mAllowedNetworkTypesListener = new AllowedNetworkTypesListener(); 152 registerAllowedNetworkTypesListener(); 153 } 154 155 /** 156 * Return preferred network mode listener 157 */ 158 @VisibleForTesting getAllowedNetworkTypesChangedListener()159 public AllowedNetworkTypesListener getAllowedNetworkTypesChangedListener() { 160 return mAllowedNetworkTypesListener; 161 } 162 registerAllowedNetworkTypesListener()163 private void registerAllowedNetworkTypesListener() { 164 int subId = mPhone.getSubId(); 165 unregisterAllowedNetworkTypesListener(); 166 if (SubscriptionManager.isValidSubscriptionId(subId)) { 167 if (mTelephonyManager != null) { 168 mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this), 169 mAllowedNetworkTypesListener); 170 } 171 } 172 } 173 unregisterAllowedNetworkTypesListener()174 private void unregisterAllowedNetworkTypesListener() { 175 mTelephonyManager.unregisterTelephonyCallback(mAllowedNetworkTypesListener); 176 } 177 178 /** 179 * Returns mNotificationTypeMap 180 */ 181 @VisibleForTesting getNotificationTypeMap()182 public Map<Integer, NotificationType> getNotificationTypeMap() { 183 return mNotificationTypeMap; 184 } 185 registerNotificationTypes()186 private void registerNotificationTypes() { 187 mNotificationTypeMap.put(NOTIFICATION_PREF_NETWORK, 188 new PrefNetworkNotification(NOTIFICATION_PREF_NETWORK)); 189 mNotificationTypeMap.put(NOTIFICATION_EMERGENCY_NETWORK, 190 new EmergencyNetworkNotification(NOTIFICATION_EMERGENCY_NETWORK)); 191 } 192 193 @Override handleMessage(Message msg)194 public void handleMessage(Message msg) { 195 switch (msg.what) { 196 case CARRIER_EVENT_VOICE_REGISTRATION: 197 case CARRIER_EVENT_DATA_REGISTRATION: 198 case CARRIER_EVENT_VOICE_DEREGISTRATION: 199 case CARRIER_EVENT_DATA_DEREGISTRATION: 200 handleConfigChanges(); 201 break; 202 case CARRIER_EVENT_IMS_CAPABILITIES_CHANGED: 203 handleImsCapabilitiesChanged(); 204 break; 205 case NOTIFICATION_EMERGENCY_NETWORK: 206 case NOTIFICATION_PREF_NETWORK: 207 Rlog.d(LOG_TAG, "sending notification after delay: " + msg.what); 208 NotificationType notificationType = mNotificationTypeMap.get(msg.what); 209 if (notificationType != null) { 210 sendNotification(notificationType); 211 } 212 break; 213 } 214 } 215 isPhoneStillRegistered()216 private boolean isPhoneStillRegistered() { 217 if (mSST.mSS == null) { 218 return true; //something has gone wrong, return true and not show the notification. 219 } 220 return (mSST.mSS.getState() == ServiceState.STATE_IN_SERVICE 221 || mSST.mSS.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE); 222 } 223 isPhoneRegisteredForWifiCalling()224 private boolean isPhoneRegisteredForWifiCalling() { 225 Rlog.d(LOG_TAG, "isPhoneRegisteredForWifiCalling: " + mPhone.isWifiCallingEnabled()); 226 return mPhone.isWifiCallingEnabled(); 227 } 228 229 /** 230 * Returns true if the radio is off or in Airplane Mode else returns false. 231 */ 232 @VisibleForTesting isRadioOffOrAirplaneMode()233 public boolean isRadioOffOrAirplaneMode() { 234 Context context = mPhone.getContext(); 235 int airplaneMode = -1; 236 try { 237 airplaneMode = Settings.Global.getInt(context.getContentResolver(), 238 Settings.Global.AIRPLANE_MODE_ON, 0); 239 } catch (Exception e) { 240 Rlog.e(LOG_TAG, "Unable to get AIRPLACE_MODE_ON."); 241 return true; 242 } 243 return (!mSST.isRadioOn() || (airplaneMode != 0)); 244 } 245 246 /** 247 * Returns true if the preferred network is set to 'Global'. 248 */ isGlobalMode()249 private boolean isGlobalMode() { 250 int preferredNetworkSetting = -1; 251 try { 252 preferredNetworkSetting = PhoneFactory.calculatePreferredNetworkType( 253 mPhone.getPhoneId()); 254 } catch (Exception e) { 255 Rlog.e(LOG_TAG, "Unable to get PREFERRED_NETWORK_MODE."); 256 return true; 257 } 258 259 if (isNrSupported()) { 260 return (preferredNetworkSetting 261 == RadioAccessFamily.getRafFromNetworkType( 262 RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA)); 263 } else { 264 return (preferredNetworkSetting == RadioAccessFamily.getRafFromNetworkType( 265 RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA)); 266 } 267 } 268 isNrSupported()269 private boolean isNrSupported() { 270 Context context = mPhone.getContext(); 271 TelephonyManager tm = ((TelephonyManager) context.getSystemService( 272 Context.TELEPHONY_SERVICE)).createForSubscriptionId(mPhone.getSubId()); 273 274 boolean isCarrierConfigEnabled = isCarrierConfigEnableNr(); 275 boolean isRadioAccessFamilySupported = checkSupportedBitmask( 276 tm.getSupportedRadioAccessFamily(), TelephonyManager.NETWORK_TYPE_BITMASK_NR); 277 boolean isNrNetworkTypeAllowed = checkSupportedBitmask( 278 tm.getAllowedNetworkTypesForReason( 279 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER), 280 TelephonyManager.NETWORK_TYPE_BITMASK_NR); 281 282 Rlog.i(LOG_TAG, "isNrSupported: " + " carrierConfigEnabled: " + isCarrierConfigEnabled 283 + ", AccessFamilySupported: " + isRadioAccessFamilySupported 284 + ", isNrNetworkTypeAllowed: " + isNrNetworkTypeAllowed); 285 286 return (isCarrierConfigEnabled && isRadioAccessFamilySupported && isNrNetworkTypeAllowed); 287 } 288 isCarrierConfigEnableNr()289 private boolean isCarrierConfigEnableNr() { 290 PersistableBundle config = 291 CarrierConfigManager.getCarrierConfigSubset( 292 mPhone.getContext(), 293 mPhone.getSubId(), 294 CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY); 295 if (config.isEmpty()) { 296 Rlog.e(LOG_TAG, "isCarrierConfigEnableNr: Cannot get config " + mPhone.getSubId()); 297 return false; 298 } 299 int[] nrAvailabilities = config.getIntArray( 300 CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY); 301 return !ArrayUtils.isEmpty(nrAvailabilities); 302 } 303 checkSupportedBitmask(@etworkTypeBitMask long supportedBitmask, @NetworkTypeBitMask long targetBitmask)304 private boolean checkSupportedBitmask(@NetworkTypeBitMask long supportedBitmask, 305 @NetworkTypeBitMask long targetBitmask) { 306 return (targetBitmask & supportedBitmask) == targetBitmask; 307 } 308 handleConfigChanges()309 private void handleConfigChanges() { 310 for (Map.Entry<Integer, NotificationType> entry : mNotificationTypeMap.entrySet()) { 311 NotificationType notificationType = entry.getValue(); 312 evaluateSendingMessageOrCancelNotification(notificationType); 313 } 314 } 315 handleAllowedNetworkTypeChanged()316 private void handleAllowedNetworkTypeChanged() { 317 NotificationType notificationType = mNotificationTypeMap.get(NOTIFICATION_PREF_NETWORK); 318 if (notificationType != null) { 319 evaluateSendingMessageOrCancelNotification(notificationType); 320 } 321 } 322 handleImsCapabilitiesChanged()323 private void handleImsCapabilitiesChanged() { 324 NotificationType notificationType = mNotificationTypeMap 325 .get(NOTIFICATION_EMERGENCY_NETWORK); 326 if (notificationType != null) { 327 evaluateSendingMessageOrCancelNotification(notificationType); 328 } 329 } 330 evaluateSendingMessageOrCancelNotification(NotificationType notificationType)331 private void evaluateSendingMessageOrCancelNotification(NotificationType notificationType) { 332 if (evaluateSendingMessage(notificationType)) { 333 Message notificationMsg = obtainMessage(notificationType.getTypeId(), null); 334 Rlog.i(LOG_TAG, "starting timer for notifications." + notificationType.getTypeId()); 335 sendMessageDelayed(notificationMsg, getDelay(notificationType)); 336 } else { 337 cancelNotification(notificationType); 338 Rlog.i(LOG_TAG, "canceling notifications: " + notificationType.getTypeId()); 339 } 340 } 341 342 /** 343 * This method adds a level of indirection, and was created so we can unit the class. 344 **/ 345 @VisibleForTesting evaluateSendingMessage(NotificationType notificationType)346 public boolean evaluateSendingMessage(NotificationType notificationType) { 347 return notificationType.sendMessage(); 348 } 349 350 /** 351 * This method adds a level of indirection, and was created so we can unit the class. 352 **/ 353 @VisibleForTesting getDelay(NotificationType notificationType)354 public int getDelay(NotificationType notificationType) { 355 return notificationType.getDelay(); 356 } 357 358 /** 359 * This method adds a level of indirection, and was created so we can unit the class. 360 **/ 361 @VisibleForTesting getNotificationBuilder(NotificationType notificationType)362 public Notification.Builder getNotificationBuilder(NotificationType notificationType) { 363 return notificationType.getNotificationBuilder(); 364 } 365 366 /** 367 * This method adds a level of indirection, and was created so we can unit the class. 368 **/ 369 @VisibleForTesting getNotificationManager(Context context)370 public NotificationManager getNotificationManager(Context context) { 371 return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 372 } 373 374 /** 375 * Post a notification to the NotificationManager for changing network type. 376 */ 377 @VisibleForTesting sendNotification(NotificationType notificationType)378 public void sendNotification(NotificationType notificationType) { 379 if (!evaluateSendingMessage(notificationType)) { 380 return; 381 } 382 383 Context context = mPhone.getContext(); 384 Notification.Builder builder = getNotificationBuilder(notificationType); 385 // set some common attributes 386 builder.setWhen(System.currentTimeMillis()) 387 .setShowWhen(true) 388 .setAutoCancel(true) 389 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) 390 .setColor(context.getResources().getColor( 391 com.android.internal.R.color.system_notification_accent_color)); 392 getNotificationManager(context).notify(notificationType.getNotificationTag(), 393 notificationType.getNotificationId(), builder.build()); 394 } 395 396 /** 397 * Cancel notifications if a registration is pending or has been sent. 398 **/ cancelNotification(NotificationType notificationType)399 public void cancelNotification(NotificationType notificationType) { 400 Context context = mPhone.getContext(); 401 removeMessages(notificationType.getTypeId()); 402 getNotificationManager(context).cancel( 403 notificationType.getNotificationTag(), notificationType.getNotificationId()); 404 } 405 406 /** 407 * Dispose the CarrierServiceStateTracker. 408 */ dispose()409 public void dispose() { 410 unregisterAllowedNetworkTypesListener(); 411 } 412 413 /** 414 * Class that defines the different types of notifications. 415 */ 416 public interface NotificationType { 417 418 /** 419 * decides if the message should be sent, Returns boolean 420 **/ sendMessage()421 boolean sendMessage(); 422 423 /** 424 * returns the interval by which the message is delayed. 425 **/ getDelay()426 int getDelay(); 427 428 /** sets the interval by which the message is delayed. 429 * @param bundle PersistableBundle 430 **/ setDelay(PersistableBundle bundle)431 void setDelay(PersistableBundle bundle); 432 433 /** 434 * Checks whether this Notification is enabled. 435 * @return {@code true} if this Notification is enabled, false otherwise 436 */ isEnabled()437 boolean isEnabled(); 438 439 /** 440 * Sets whether this Notification is enabled. If disabled, it will not build notification. 441 * @param bundle PersistableBundle 442 */ setEnabled(PersistableBundle bundle)443 void setEnabled(PersistableBundle bundle); 444 445 /** 446 * returns notification type id. 447 **/ getTypeId()448 int getTypeId(); 449 450 /** 451 * returns notification id. 452 **/ getNotificationId()453 int getNotificationId(); 454 455 /** 456 * returns notification tag. 457 **/ getNotificationTag()458 String getNotificationTag(); 459 460 /** 461 * returns the notification builder, for the notification to be displayed. 462 **/ getNotificationBuilder()463 Notification.Builder getNotificationBuilder(); 464 } 465 466 /** 467 * Class that defines the network notification, which is shown when the phone cannot camp on 468 * a network, and has 'preferred mode' set to global. 469 */ 470 public class PrefNetworkNotification implements NotificationType { 471 472 private final int mTypeId; 473 private int mDelay = UNINITIALIZED_DELAY_VALUE; 474 private boolean mEnabled = false; 475 PrefNetworkNotification(int typeId)476 PrefNetworkNotification(int typeId) { 477 this.mTypeId = typeId; 478 } 479 480 /** sets the interval by which the message is delayed. 481 * @param bundle PersistableBundle 482 **/ setDelay(PersistableBundle bundle)483 public void setDelay(PersistableBundle bundle) { 484 if (bundle == null) { 485 Rlog.e(LOG_TAG, "bundle is null"); 486 return; 487 } 488 this.mDelay = bundle.getInt( 489 CarrierConfigManager.KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT); 490 Rlog.i(LOG_TAG, "reading time to delay notification pref network: " + mDelay); 491 } 492 getDelay()493 public int getDelay() { 494 return mDelay; 495 } 496 497 /** 498 * Checks whether this Notification is enabled. 499 * @return {@code true} if this Notification is enabled, false otherwise 500 */ isEnabled()501 public boolean isEnabled() { 502 return mEnabled; 503 } 504 505 /** 506 * Sets whether this Notification is enabled. If disabled, it will not build notification. 507 * @param bundle PersistableBundle 508 */ setEnabled(PersistableBundle bundle)509 public void setEnabled(PersistableBundle bundle) { 510 if (bundle == null) { 511 Rlog.e(LOG_TAG, "bundle is null"); 512 return; 513 } 514 mEnabled = !bundle.getBoolean( 515 CarrierConfigManager.KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL); 516 Rlog.i(LOG_TAG, "reading enabled notification pref network: " + mEnabled); 517 } 518 getTypeId()519 public int getTypeId() { 520 return mTypeId; 521 } 522 getNotificationId()523 public int getNotificationId() { 524 return mPhone.getSubId(); 525 } 526 getNotificationTag()527 public String getNotificationTag() { 528 return PREF_NETWORK_NOTIFICATION_TAG; 529 } 530 531 /** 532 * Contains logic on sending notifications. 533 */ sendMessage()534 public boolean sendMessage() { 535 Rlog.i(LOG_TAG, "PrefNetworkNotification: sendMessage() w/values: " 536 + "," + mEnabled + "," + isPhoneStillRegistered() + "," + mDelay 537 + "," + isGlobalMode() + "," + mSST.isRadioOn()); 538 if (!mEnabled || mDelay == UNINITIALIZED_DELAY_VALUE || isPhoneStillRegistered() 539 || isGlobalMode() || isRadioOffOrAirplaneMode()) { 540 return false; 541 } 542 return true; 543 } 544 545 /** 546 * Builds a partial notificaiton builder, and returns it. 547 */ getNotificationBuilder()548 public Notification.Builder getNotificationBuilder() { 549 Context context = mPhone.getContext(); 550 Intent notificationIntent = new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS); 551 notificationIntent.putExtra("expandable", true); 552 PendingIntent settingsIntent = PendingIntent.getActivity(context, 0, notificationIntent, 553 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE); 554 Resources res = SubscriptionManager.getResourcesForSubId(context, mPhone.getSubId()); 555 CharSequence title = res.getText( 556 com.android.internal.R.string.NetworkPreferenceSwitchTitle); 557 CharSequence details = res.getText( 558 com.android.internal.R.string.NetworkPreferenceSwitchSummary); 559 return new Notification.Builder(context) 560 .setContentTitle(title) 561 .setStyle(new Notification.BigTextStyle().bigText(details)) 562 .setContentText(details) 563 .setChannelId(NotificationChannelController.CHANNEL_ID_ALERT) 564 .setContentIntent(settingsIntent); 565 } 566 } 567 568 /** 569 * Class that defines the emergency notification, which is shown when Wi-Fi Calling is 570 * available. 571 */ 572 public class EmergencyNetworkNotification implements NotificationType { 573 574 private final int mTypeId; 575 private int mDelay = UNINITIALIZED_DELAY_VALUE; 576 EmergencyNetworkNotification(int typeId)577 EmergencyNetworkNotification(int typeId) { 578 this.mTypeId = typeId; 579 } 580 581 /** sets the interval by which the message is delayed. 582 * @param bundle PersistableBundle 583 **/ setDelay(PersistableBundle bundle)584 public void setDelay(PersistableBundle bundle) { 585 if (bundle == null) { 586 Rlog.e(LOG_TAG, "bundle is null"); 587 return; 588 } 589 this.mDelay = bundle.getInt( 590 CarrierConfigManager.KEY_EMERGENCY_NOTIFICATION_DELAY_INT); 591 Rlog.i(LOG_TAG, "reading time to delay notification emergency: " + mDelay); 592 } 593 getDelay()594 public int getDelay() { 595 return mDelay; 596 } 597 598 /** 599 * Checks whether this Notification is enabled. 600 * @return {@code true} if this Notification is enabled, false otherwise 601 */ isEnabled()602 public boolean isEnabled() { 603 return true; 604 } 605 606 /** 607 * Sets whether this Notification is enabled. If disabled, it will not build notification. 608 * @param bundle PersistableBundle 609 */ setEnabled(PersistableBundle bundle)610 public void setEnabled(PersistableBundle bundle) { 611 // always allowed. There is no config to hide notifications. 612 } 613 getTypeId()614 public int getTypeId() { 615 return mTypeId; 616 } 617 getNotificationId()618 public int getNotificationId() { 619 return mPhone.getSubId(); 620 } 621 getNotificationTag()622 public String getNotificationTag() { 623 return EMERGENCY_NOTIFICATION_TAG; 624 } 625 626 /** 627 * Contains logic on sending notifications, 628 */ sendMessage()629 public boolean sendMessage() { 630 Rlog.i(LOG_TAG, "EmergencyNetworkNotification: sendMessage() w/values: " 631 + "," + mDelay + "," + isPhoneRegisteredForWifiCalling() + "," 632 + mSST.isRadioOn()); 633 if (mDelay == UNINITIALIZED_DELAY_VALUE || !isPhoneRegisteredForWifiCalling()) { 634 return false; 635 } 636 return true; 637 } 638 639 /** 640 * Builds a partial notificaiton builder, and returns it. 641 */ getNotificationBuilder()642 public Notification.Builder getNotificationBuilder() { 643 Context context = mPhone.getContext(); 644 Resources res = SubscriptionManager.getResourcesForSubId(context, mPhone.getSubId()); 645 CharSequence title = res.getText( 646 com.android.internal.R.string.EmergencyCallWarningTitle); 647 CharSequence details = res.getText( 648 com.android.internal.R.string.EmergencyCallWarningSummary); 649 return new Notification.Builder(context) 650 .setContentTitle(title) 651 .setStyle(new Notification.BigTextStyle().bigText(details)) 652 .setContentText(details) 653 .setOngoing(true) 654 .setChannelId(NotificationChannelController.CHANNEL_ID_WFC); 655 } 656 } 657 } 658