1 /* 2 * Copyright (C) 2017 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.app.UiModeManager.PROJECTION_TYPE_AUTOMOTIVE; 20 import static android.hardware.radio.V1_0.DeviceStateType.CHARGING_STATE; 21 import static android.hardware.radio.V1_0.DeviceStateType.LOW_DATA_EXPECTED; 22 import static android.hardware.radio.V1_0.DeviceStateType.POWER_SAVE_MODE; 23 import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK; 24 25 import android.annotation.NonNull; 26 import android.app.UiModeManager; 27 import android.content.BroadcastReceiver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.IntentFilter; 31 import android.hardware.display.DisplayManager; 32 import android.hardware.radio.V1_5.IndicationFilter; 33 import android.net.ConnectivityManager; 34 import android.net.Network; 35 import android.net.NetworkCapabilities; 36 import android.net.NetworkRequest; 37 import android.net.TetheringManager; 38 import android.os.BatteryManager; 39 import android.os.Handler; 40 import android.os.Message; 41 import android.os.PowerManager; 42 import android.os.Registrant; 43 import android.os.RegistrantList; 44 import android.provider.Settings; 45 import android.telephony.AccessNetworkConstants.AccessNetworkType; 46 import android.telephony.NetworkRegistrationInfo; 47 import android.util.LocalLog; 48 import android.view.Display; 49 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.telephony.flags.FeatureFlags; 52 import com.android.internal.util.IndentingPrintWriter; 53 import com.android.telephony.Rlog; 54 55 import java.io.FileDescriptor; 56 import java.io.PrintWriter; 57 import java.util.ArrayList; 58 import java.util.HashSet; 59 import java.util.Set; 60 61 /** 62 * The device state monitor monitors the device state such as charging state, power saving sate, 63 * and then passes down the information to the radio modem for the modem to perform its own 64 * proprietary power saving strategy. Device state monitor also turns off the unsolicited 65 * response from the modem when the device does not need to receive it, for example, device's 66 * screen is off and does not have activities like tethering, remote display, etc...This effectively 67 * prevents the CPU from waking up by those unnecessary unsolicited responses such as signal 68 * strength update. 69 */ 70 public class DeviceStateMonitor extends Handler { 71 protected static final boolean DBG = false; /* STOPSHIP if true */ 72 protected static final String TAG = DeviceStateMonitor.class.getSimpleName(); 73 74 static final int EVENT_RIL_CONNECTED = 0; 75 static final int EVENT_AUTOMOTIVE_PROJECTION_STATE_CHANGED = 1; 76 @VisibleForTesting 77 static final int EVENT_SCREEN_STATE_CHANGED = 2; 78 static final int EVENT_POWER_SAVE_MODE_CHANGED = 3; 79 @VisibleForTesting 80 static final int EVENT_CHARGING_STATE_CHANGED = 4; 81 static final int EVENT_TETHERING_STATE_CHANGED = 5; 82 static final int EVENT_RADIO_AVAILABLE = 6; 83 @VisibleForTesting 84 static final int EVENT_WIFI_CONNECTION_CHANGED = 7; 85 static final int EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH = 8; 86 static final int EVENT_RADIO_ON = 9; 87 static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 10; 88 89 private static final int WIFI_UNAVAILABLE = 0; 90 private static final int WIFI_AVAILABLE = 1; 91 92 private static final int NR_NSA_TRACKING_INDICATIONS_OFF = 0; 93 private static final int NR_NSA_TRACKING_INDICATIONS_EXTENDED = 1; 94 private static final int NR_NSA_TRACKING_INDICATIONS_ALWAYS_ON = 2; 95 96 private final Phone mPhone; 97 @NonNull 98 private final FeatureFlags mFeatureFlags; 99 100 private final LocalLog mLocalLog = new LocalLog(64); 101 102 private final RegistrantList mPhysicalChannelConfigRegistrants = new RegistrantList(); 103 private final RegistrantList mSignalStrengthReportDecisionCallbackRegistrants = 104 new RegistrantList(); 105 private final RegistrantList mScreenStateRegistrants = new RegistrantList(); 106 107 private final NetworkRequest mWifiNetworkRequest = 108 new NetworkRequest.Builder() 109 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 110 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 111 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 112 .build(); 113 114 private final ConnectivityManager.NetworkCallback mNetworkCallback = 115 new ConnectivityManager.NetworkCallback() { 116 Set<Network> mWifiNetworks = new HashSet<>(); 117 118 @Override 119 public void onAvailable(Network network) { 120 synchronized (mWifiNetworks) { 121 if (mWifiNetworks.size() == 0) { 122 // We just connected to Wifi, so send an update. 123 obtainMessage(EVENT_WIFI_CONNECTION_CHANGED, WIFI_AVAILABLE, 0).sendToTarget(); 124 log("Wifi (default) connected", true); 125 } 126 mWifiNetworks.add(network); 127 } 128 } 129 130 @Override 131 public void onLost(Network network) { 132 synchronized (mWifiNetworks) { 133 mWifiNetworks.remove(network); 134 if (mWifiNetworks.size() == 0) { 135 // We just disconnected from the last connected wifi, so send an update. 136 obtainMessage( 137 EVENT_WIFI_CONNECTION_CHANGED, WIFI_UNAVAILABLE, 0).sendToTarget(); 138 log("Wifi (default) disconnected", true); 139 } 140 } 141 } 142 }; 143 144 /** 145 * Flag for wifi/usb/bluetooth tethering turned on or not 146 */ 147 private boolean mIsTetheringOn; 148 149 /** 150 * Screen state provided by Display Manager. True indicates one of the screen is on, otherwise 151 * all off. 152 */ 153 private boolean mIsScreenOn; 154 155 /** 156 * Indicating the device is plugged in and is supplying sufficient power that the battery level 157 * is going up (or the battery is fully charged). See BatteryManager.isCharging() for the 158 * details 159 */ 160 private boolean mIsCharging; 161 162 /** 163 * Flag for device power save mode. See PowerManager.isPowerSaveMode() for the details. 164 * Note that it is not possible both mIsCharging and mIsPowerSaveOn are true at the same time. 165 * The system will automatically end power save mode when the device starts charging. 166 */ 167 private boolean mIsPowerSaveOn; 168 169 /** 170 * Low data expected mode. True indicates low data traffic is expected, for example, when the 171 * device is idle (e.g. screen is off and not doing tethering in the background). Note this 172 * doesn't mean no data is expected. 173 */ 174 private boolean mIsLowDataExpected; 175 176 /** 177 * Wifi is connected. True means both that cellular is likely to be asleep when the screen is 178 * on and that in most cases the device location is relatively close to the WiFi AP. This means 179 * that fewer location updates should be provided by cellular. 180 */ 181 private boolean mIsWifiConnected; 182 183 /** 184 * Automotive projection is active. True means the device is currently connected to Android 185 * Auto. This should be handled by mIsScreenOn, but the Android Auto display is private and not 186 * accessible by DeviceStateMonitor from DisplayMonitor. 187 */ 188 private boolean mIsAutomotiveProjectionActive; 189 190 /** 191 * Radio is on. False means that radio is either off or not available and it is ok to reduce 192 * commands to the radio to avoid unnecessary power consumption. 193 */ 194 private boolean mIsRadioOn; 195 196 /** 197 * True indicates we should always enable the signal strength reporting from radio. 198 */ 199 private boolean mIsAlwaysSignalStrengthReportingEnabled; 200 201 @VisibleForTesting 202 static final int CELL_INFO_INTERVAL_SHORT_MS = 2000; 203 @VisibleForTesting 204 static final int CELL_INFO_INTERVAL_LONG_MS = 10000; 205 206 /** The minimum required wait time between cell info requests to the modem */ 207 private int mCellInfoMinInterval = CELL_INFO_INTERVAL_SHORT_MS; 208 209 /** 210 * The unsolicited response filter. See IndicationFilter defined in types.hal for the definition 211 * of each bit. 212 */ 213 private int mUnsolicitedResponseFilter = IndicationFilter.ALL; 214 215 private final DisplayManager.DisplayListener mDisplayListener = 216 new DisplayManager.DisplayListener() { 217 @Override 218 public void onDisplayAdded(int displayId) { } 219 220 @Override 221 public void onDisplayRemoved(int displayId) { 222 /* adapter for virtual display removed */ 223 boolean screenOn = isScreenOn(); 224 Message msg = obtainMessage(EVENT_SCREEN_STATE_CHANGED); 225 msg.arg1 = screenOn ? 1 : 0; 226 sendMessage(msg); 227 } 228 229 @Override 230 public void onDisplayChanged(int displayId) { 231 boolean screenOn = isScreenOn(); 232 Message msg = obtainMessage(EVENT_SCREEN_STATE_CHANGED); 233 msg.arg1 = screenOn ? 1 : 0; 234 sendMessage(msg); 235 } 236 }; 237 238 /** 239 * Device state broadcast receiver 240 */ 241 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 242 @Override 243 public void onReceive(Context context, Intent intent) { 244 log("received: " + intent, true); 245 246 Message msg; 247 switch (intent.getAction()) { 248 case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED: 249 msg = obtainMessage(EVENT_POWER_SAVE_MODE_CHANGED); 250 msg.arg1 = isPowerSaveModeOn() ? 1 : 0; 251 log("Power Save mode " + ((msg.arg1 == 1) ? "on" : "off"), true); 252 break; 253 case BatteryManager.ACTION_CHARGING: 254 msg = obtainMessage(EVENT_CHARGING_STATE_CHANGED); 255 msg.arg1 = 1; // charging 256 break; 257 case BatteryManager.ACTION_DISCHARGING: 258 msg = obtainMessage(EVENT_CHARGING_STATE_CHANGED); 259 msg.arg1 = 0; // not charging 260 break; 261 case TetheringManager.ACTION_TETHER_STATE_CHANGED: 262 ArrayList<String> activeTetherIfaces = intent.getStringArrayListExtra( 263 TetheringManager.EXTRA_ACTIVE_TETHER); 264 265 boolean isTetheringOn = activeTetherIfaces != null 266 && activeTetherIfaces.size() > 0; 267 log("Tethering " + (isTetheringOn ? "on" : "off"), true); 268 msg = obtainMessage(EVENT_TETHERING_STATE_CHANGED); 269 msg.arg1 = isTetheringOn ? 1 : 0; 270 break; 271 default: 272 log("Unexpected broadcast intent: " + intent, false); 273 return; 274 } 275 sendMessage(msg); 276 } 277 }; 278 279 /** 280 * Device state monitor constructor. Note that each phone object should have its own device 281 * state monitor, meaning there will be two device monitors on the multi-sim device. 282 * 283 * @param phone Phone object 284 */ DeviceStateMonitor(Phone phone, @NonNull FeatureFlags featureFlags)285 public DeviceStateMonitor(Phone phone, @NonNull FeatureFlags featureFlags) { 286 mPhone = phone; 287 mFeatureFlags = featureFlags; 288 DisplayManager dm = (DisplayManager) phone.getContext().getSystemService( 289 Context.DISPLAY_SERVICE); 290 dm.registerDisplayListener(mDisplayListener, null); 291 292 mIsPowerSaveOn = isPowerSaveModeOn(); 293 mIsCharging = isDeviceCharging(); 294 mIsScreenOn = isScreenOn(); 295 mIsRadioOn = isRadioOn(); 296 mIsAutomotiveProjectionActive = isAutomotiveProjectionActive(); 297 // Assuming tethering is always off after boot up. 298 mIsTetheringOn = false; 299 mIsLowDataExpected = false; 300 301 log("DeviceStateMonitor mIsTetheringOn=" + mIsTetheringOn 302 + ", mIsScreenOn=" + mIsScreenOn 303 + ", mIsCharging=" + mIsCharging 304 + ", mIsPowerSaveOn=" + mIsPowerSaveOn 305 + ", mIsLowDataExpected=" + mIsLowDataExpected 306 + ", mIsAutomotiveProjectionActive=" + mIsAutomotiveProjectionActive 307 + ", mIsWifiConnected=" + mIsWifiConnected 308 + ", mIsAlwaysSignalStrengthReportingEnabled=" 309 + mIsAlwaysSignalStrengthReportingEnabled 310 + ", mIsRadioOn=" + mIsRadioOn, false); 311 312 final IntentFilter filter = new IntentFilter(); 313 filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); 314 filter.addAction(BatteryManager.ACTION_CHARGING); 315 filter.addAction(BatteryManager.ACTION_DISCHARGING); 316 filter.addAction(TetheringManager.ACTION_TETHER_STATE_CHANGED); 317 mPhone.getContext().registerReceiver(mBroadcastReceiver, filter, null, mPhone); 318 319 mPhone.mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null); 320 mPhone.mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 321 mPhone.mCi.registerForOn(this, EVENT_RADIO_ON, null); 322 mPhone.mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 323 324 ConnectivityManager cm = (ConnectivityManager) phone.getContext().getSystemService( 325 Context.CONNECTIVITY_SERVICE); 326 cm.registerNetworkCallback(mWifiNetworkRequest, mNetworkCallback); 327 328 UiModeManager umm = (UiModeManager) phone.getContext().getSystemService( 329 Context.UI_MODE_SERVICE); 330 umm.addOnProjectionStateChangedListener(PROJECTION_TYPE_AUTOMOTIVE, 331 phone.getContext().getMainExecutor(), 332 (t, pkgs) -> { 333 Message msg = obtainMessage(EVENT_AUTOMOTIVE_PROJECTION_STATE_CHANGED); 334 msg.arg1 = Math.min(pkgs.size(), 1); 335 sendMessage(msg); 336 }); 337 } 338 339 /** 340 * @return True if low data is expected 341 */ isLowDataExpected()342 private boolean isLowDataExpected() { 343 return (!mIsCharging && !mIsTetheringOn && !mIsScreenOn) || !mIsRadioOn; 344 } 345 346 /** 347 * @return The minimum period between CellInfo requests to the modem 348 */ 349 @VisibleForTesting computeCellInfoMinInterval()350 public int computeCellInfoMinInterval() { 351 // The screen is on and we're either on cellular or charging. Screen on + Charging is 352 // a likely vehicular scenario, even if there is a nomadic AP. 353 if (mIsScreenOn && !mIsWifiConnected) { 354 // Screen on without WiFi - We are in a high power likely mobile situation. 355 return CELL_INFO_INTERVAL_SHORT_MS; 356 } else if (mIsScreenOn && mIsCharging) { 357 // Screen is on and we're charging, so we favor accuracy over power. 358 return CELL_INFO_INTERVAL_SHORT_MS; 359 } else { 360 // If the screen is off, apps should not need cellular location at rapid intervals. 361 // If the screen is on but we are on wifi and not charging then cellular location 362 // accuracy is not crucial, so favor modem power saving over high accuracy. 363 return CELL_INFO_INTERVAL_LONG_MS; 364 } 365 } 366 367 /** 368 * @return True if signal strength update should be enabled. See details in 369 * android.hardware.radio@1.2::IndicationFilter::SIGNAL_STRENGTH. 370 */ shouldEnableSignalStrengthReports()371 private boolean shouldEnableSignalStrengthReports() { 372 // We should enable signal strength update if one of the following condition is true. 373 // 1. Whenever the conditions for high power usage are met. 374 // 2. Any of system services is registrating to always listen to signal strength changes 375 // and the radio is on (if radio is off no indications should be sent regardless, but 376 // in the rare case that something registers/unregisters for always-on indications 377 // and the radio is off, we might as well ignore it). 378 return shouldEnableHighPowerConsumptionIndications() 379 || (mIsAlwaysSignalStrengthReportingEnabled && mIsRadioOn); 380 } 381 382 /** 383 * @return True if full network state update should be enabled. When off, only significant 384 * changes will trigger the network update unsolicited response. See details in 385 * android.hardware.radio@1.2::IndicationFilter::FULL_NETWORK_STATE. 386 */ shouldEnableFullNetworkStateReports()387 private boolean shouldEnableFullNetworkStateReports() { 388 return shouldEnableNrTrackingIndications(); 389 } 390 391 /** 392 * @return True if data call dormancy changed update should be enabled. See details in 393 * android.hardware.radio@1.2::IndicationFilter::DATA_CALL_DORMANCY_CHANGED. 394 */ shouldEnableDataCallDormancyChangedReports()395 private boolean shouldEnableDataCallDormancyChangedReports() { 396 return shouldEnableNrTrackingIndications(); 397 } 398 399 /** 400 * @return True if link capacity estimate update should be enabled. See details in 401 * android.hardware.radio@1.2::IndicationFilter::LINK_CAPACITY_ESTIMATE. 402 */ shouldEnableLinkCapacityEstimateReports()403 private boolean shouldEnableLinkCapacityEstimateReports() { 404 return shouldEnableHighPowerConsumptionIndications(); 405 } 406 407 /** 408 * @return True if physical channel config update should be enabled. See details in 409 * android.hardware.radio@1.2::IndicationFilter::PHYSICAL_CHANNEL_CONFIG. 410 */ shouldEnablePhysicalChannelConfigReports()411 private boolean shouldEnablePhysicalChannelConfigReports() { 412 return shouldEnableNrTrackingIndications(); 413 } 414 415 /** 416 * @return True if barring info update should be enabled. See details in 417 * android.hardware.radio@1.5::IndicationFilter::BARRING_INFO. 418 */ shouldEnableBarringInfoReports()419 private boolean shouldEnableBarringInfoReports() { 420 return shouldEnableHighPowerConsumptionIndications(); 421 } 422 423 /** 424 * A common policy to determine if we should enable the necessary indications update, 425 * for power consumption's sake. 426 * 427 * @return True if the response update should be enabled. 428 */ shouldEnableHighPowerConsumptionIndications()429 public boolean shouldEnableHighPowerConsumptionIndications() { 430 // We should enable indications reports if radio is on and one of the following conditions 431 // is true: 432 // 1. The device is charging. 433 // 2. When the screen is on. 434 // 3. When the tethering is on. 435 // 4. When automotive projection (Android Auto) is on. 436 return (mIsCharging || mIsScreenOn || mIsTetheringOn || mIsAutomotiveProjectionActive) 437 && mIsRadioOn; 438 } 439 440 /** 441 * For 5G NSA devices, a policy to determine if we should enable NR tracking indications. 442 * 443 * @return True if the response update should be enabled. 444 */ shouldEnableNrTrackingIndications()445 private boolean shouldEnableNrTrackingIndications() { 446 int trackingMode = Settings.Global.getInt(mPhone.getContext().getContentResolver(), 447 Settings.Global.NR_NSA_TRACKING_SCREEN_OFF_MODE, NR_NSA_TRACKING_INDICATIONS_OFF); 448 switch (trackingMode) { 449 case NR_NSA_TRACKING_INDICATIONS_ALWAYS_ON: 450 return true; 451 case NR_NSA_TRACKING_INDICATIONS_EXTENDED: 452 if (mPhone.getServiceState().getNrState() 453 == NetworkRegistrationInfo.NR_STATE_CONNECTED) { 454 return true; 455 } 456 // fallthrough 457 case NR_NSA_TRACKING_INDICATIONS_OFF: 458 return shouldEnableHighPowerConsumptionIndications(); 459 default: 460 return shouldEnableHighPowerConsumptionIndications(); 461 } 462 } 463 464 /** 465 * Set if Telephony need always report signal strength. 466 * 467 * @param isEnable 468 */ setAlwaysReportSignalStrength(boolean isEnable)469 public void setAlwaysReportSignalStrength(boolean isEnable) { 470 Message msg = obtainMessage(EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH); 471 msg.arg1 = isEnable ? 1 : 0; 472 sendMessage(msg); 473 } 474 475 /** 476 * Message handler 477 * 478 * @param msg The message 479 */ 480 @Override handleMessage(Message msg)481 public void handleMessage(Message msg) { 482 log("handleMessage msg=" + msg, false); 483 switch (msg.what) { 484 case EVENT_RIL_CONNECTED: 485 case EVENT_RADIO_AVAILABLE: 486 onReset(); 487 break; 488 case EVENT_RADIO_ON: 489 onUpdateDeviceState(msg.what, /* state= */ true); 490 break; 491 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 492 onUpdateDeviceState(msg.what, /* state= */ false); 493 break; 494 case EVENT_SCREEN_STATE_CHANGED: 495 case EVENT_POWER_SAVE_MODE_CHANGED: 496 case EVENT_CHARGING_STATE_CHANGED: 497 case EVENT_TETHERING_STATE_CHANGED: 498 case EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH: 499 case EVENT_AUTOMOTIVE_PROJECTION_STATE_CHANGED: 500 onUpdateDeviceState(msg.what, msg.arg1 != 0); 501 break; 502 case EVENT_WIFI_CONNECTION_CHANGED: 503 onUpdateDeviceState(msg.what, msg.arg1 != WIFI_UNAVAILABLE); 504 break; 505 default: 506 throw new IllegalStateException("Unexpected message arrives. msg = " + msg.what); 507 } 508 } 509 510 /** 511 * Update the device and send the information to the modem. 512 * 513 * @param eventType Device state event type 514 * @param state True if enabled/on, otherwise disabled/off. 515 */ onUpdateDeviceState(int eventType, boolean state)516 private void onUpdateDeviceState(int eventType, boolean state) { 517 final boolean shouldEnableBarringInfoReportsOld = shouldEnableBarringInfoReports(); 518 final boolean wasHighPowerEnabled = shouldEnableHighPowerConsumptionIndications(); 519 boolean wasScreenOn = mIsScreenOn; 520 switch (eventType) { 521 case EVENT_SCREEN_STATE_CHANGED: 522 if (mIsScreenOn == state) return; 523 mIsScreenOn = state; 524 break; 525 case EVENT_CHARGING_STATE_CHANGED: 526 if (mIsCharging == state) return; 527 mIsCharging = state; 528 sendDeviceState(CHARGING_STATE, mIsCharging); 529 break; 530 case EVENT_RADIO_ON: 531 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 532 if (mIsRadioOn == state) return; 533 mIsRadioOn = state; 534 break; 535 case EVENT_TETHERING_STATE_CHANGED: 536 if (mIsTetheringOn == state) return; 537 mIsTetheringOn = state; 538 break; 539 case EVENT_POWER_SAVE_MODE_CHANGED: 540 if (mIsPowerSaveOn == state) return; 541 mIsPowerSaveOn = state; 542 sendDeviceState(POWER_SAVE_MODE, mIsPowerSaveOn); 543 break; 544 case EVENT_WIFI_CONNECTION_CHANGED: 545 if (mIsWifiConnected == state) return; 546 mIsWifiConnected = state; 547 break; 548 case EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH: 549 if (mIsAlwaysSignalStrengthReportingEnabled == state) return; 550 mIsAlwaysSignalStrengthReportingEnabled = state; 551 break; 552 case EVENT_AUTOMOTIVE_PROJECTION_STATE_CHANGED: 553 if (mIsAutomotiveProjectionActive == state) return; 554 mIsAutomotiveProjectionActive = state; 555 break; 556 default: 557 return; 558 } 559 560 final boolean isHighPowerEnabled = shouldEnableHighPowerConsumptionIndications(); 561 if (wasHighPowerEnabled != isHighPowerEnabled) { 562 mPhone.notifyDeviceIdleStateChanged(!isHighPowerEnabled /*isIdle*/); 563 } 564 565 final int newCellInfoMinInterval = computeCellInfoMinInterval(); 566 if (mCellInfoMinInterval != newCellInfoMinInterval) { 567 mCellInfoMinInterval = newCellInfoMinInterval; 568 setCellInfoMinInterval(mCellInfoMinInterval); 569 log("CellInfo Min Interval Updated to " + newCellInfoMinInterval, true); 570 } 571 572 if (mIsLowDataExpected != isLowDataExpected()) { 573 mIsLowDataExpected = !mIsLowDataExpected; 574 sendDeviceState(LOW_DATA_EXPECTED, mIsLowDataExpected); 575 } 576 577 // Registration Failure is always reported. 578 int newFilter = IndicationFilter.REGISTRATION_FAILURE; 579 580 if (shouldEnableSignalStrengthReports()) { 581 newFilter |= IndicationFilter.SIGNAL_STRENGTH; 582 } 583 584 if (shouldEnableFullNetworkStateReports()) { 585 newFilter |= IndicationFilter.FULL_NETWORK_STATE; 586 } 587 588 if (shouldEnableDataCallDormancyChangedReports()) { 589 newFilter |= IndicationFilter.DATA_CALL_DORMANCY_CHANGED; 590 } 591 592 if (shouldEnableLinkCapacityEstimateReports()) { 593 newFilter |= IndicationFilter.LINK_CAPACITY_ESTIMATE; 594 } 595 596 if (shouldEnablePhysicalChannelConfigReports()) { 597 newFilter |= IndicationFilter.PHYSICAL_CHANNEL_CONFIG; 598 } 599 600 final boolean shouldEnableBarringInfoReports = shouldEnableBarringInfoReports(); 601 if (shouldEnableBarringInfoReports) { 602 newFilter |= IndicationFilter.BARRING_INFO; 603 } 604 605 // notify PhysicalChannelConfig registrants if state changes 606 if ((newFilter & IndicationFilter.PHYSICAL_CHANNEL_CONFIG) 607 != (mUnsolicitedResponseFilter & IndicationFilter.PHYSICAL_CHANNEL_CONFIG)) { 608 mPhysicalChannelConfigRegistrants.notifyResult( 609 (newFilter & IndicationFilter.PHYSICAL_CHANNEL_CONFIG) != 0); 610 } 611 612 setUnsolResponseFilter(newFilter, false); 613 614 // Pull barring info AFTER setting filter, the order matters 615 if (shouldEnableBarringInfoReports && !shouldEnableBarringInfoReportsOld) { 616 if (DBG) log("Manually pull barring info...", true); 617 // use a null message since we don't care of receiving response 618 mPhone.mCi.getBarringInfo(null); 619 } 620 621 // Determine whether to notify registrants about the non-terrestrial signal strength change. 622 if (shouldEnableSignalStrengthReports()) { 623 mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(true); 624 } else { 625 mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(false); 626 } 627 628 if (mFeatureFlags.carrierRoamingNbIotNtn()) { 629 // Determine whether to notify registrants about the screen on, off state change. 630 if (wasScreenOn != mIsScreenOn) { 631 mScreenStateRegistrants.notifyResult(mIsScreenOn); 632 } 633 } 634 } 635 636 /** 637 * Called when RIL is connected during boot up or radio becomes available after modem restart. 638 * 639 * When modem crashes, if the user turns the screen off before RIL reconnects, device 640 * state and filter cannot be sent to modem. Resend the state here so that modem 641 * has the correct state (to stop signal strength reporting, etc). 642 */ onReset()643 private void onReset() { 644 log("onReset.", true); 645 sendDeviceState(CHARGING_STATE, mIsCharging); 646 sendDeviceState(LOW_DATA_EXPECTED, mIsLowDataExpected); 647 sendDeviceState(POWER_SAVE_MODE, mIsPowerSaveOn); 648 setUnsolResponseFilter(mUnsolicitedResponseFilter, true); 649 setLinkCapacityReportingCriteria(); 650 setCellInfoMinInterval(mCellInfoMinInterval); 651 } 652 653 /** 654 * Convert the device state type into string 655 * 656 * @param type Device state type 657 * @return The converted string 658 */ deviceTypeToString(int type)659 private String deviceTypeToString(int type) { 660 switch (type) { 661 case CHARGING_STATE: return "CHARGING_STATE"; 662 case LOW_DATA_EXPECTED: return "LOW_DATA_EXPECTED"; 663 case POWER_SAVE_MODE: return "POWER_SAVE_MODE"; 664 default: return "UNKNOWN"; 665 } 666 } 667 668 /** 669 * Send the device state to the modem. 670 * 671 * @param type Device state type. See DeviceStateType defined in types.hal. 672 * @param state True if enabled/on, otherwise disabled/off 673 */ sendDeviceState(int type, boolean state)674 private void sendDeviceState(int type, boolean state) { 675 log("send type: " + deviceTypeToString(type) + ", state=" + state, true); 676 mPhone.mCi.sendDeviceState(type, state, null); 677 } 678 679 /** 680 * Turn on/off the unsolicited response from the modem. 681 * 682 * @param newFilter See UnsolicitedResponseFilter in types.hal for the definition of each bit. 683 * @param force Always set the filter when true. 684 */ setUnsolResponseFilter(int newFilter, boolean force)685 private void setUnsolResponseFilter(int newFilter, boolean force) { 686 if (force || newFilter != mUnsolicitedResponseFilter) { 687 log("old filter: " + mUnsolicitedResponseFilter + ", new filter: " + newFilter, true); 688 mPhone.mCi.setUnsolResponseFilter(newFilter, null); 689 mUnsolicitedResponseFilter = newFilter; 690 } 691 } 692 setLinkCapacityReportingCriteria()693 private void setLinkCapacityReportingCriteria() { 694 mPhone.setLinkCapacityReportingCriteria(LINK_CAPACITY_DOWNLINK_THRESHOLDS, 695 LINK_CAPACITY_UPLINK_THRESHOLDS, AccessNetworkType.GERAN); 696 mPhone.setLinkCapacityReportingCriteria(LINK_CAPACITY_DOWNLINK_THRESHOLDS, 697 LINK_CAPACITY_UPLINK_THRESHOLDS, AccessNetworkType.UTRAN); 698 mPhone.setLinkCapacityReportingCriteria(LINK_CAPACITY_DOWNLINK_THRESHOLDS, 699 LINK_CAPACITY_UPLINK_THRESHOLDS, AccessNetworkType.EUTRAN); 700 mPhone.setLinkCapacityReportingCriteria(LINK_CAPACITY_DOWNLINK_THRESHOLDS, 701 LINK_CAPACITY_UPLINK_THRESHOLDS, AccessNetworkType.CDMA2000); 702 if (mPhone.getHalVersion(HAL_SERVICE_NETWORK).greaterOrEqual(RIL.RADIO_HAL_VERSION_1_5)) { 703 mPhone.setLinkCapacityReportingCriteria(LINK_CAPACITY_DOWNLINK_THRESHOLDS, 704 LINK_CAPACITY_UPLINK_THRESHOLDS, AccessNetworkType.NGRAN); 705 } 706 } 707 setCellInfoMinInterval(int rate)708 private void setCellInfoMinInterval(int rate) { 709 mPhone.setCellInfoMinInterval(rate); 710 } 711 712 /** 713 * @return True if the device is currently in power save mode. 714 * See {@link android.os.BatteryManager#isPowerSaveMode BatteryManager.isPowerSaveMode()}. 715 */ isPowerSaveModeOn()716 private boolean isPowerSaveModeOn() { 717 final PowerManager pm = (PowerManager) mPhone.getContext().getSystemService( 718 Context.POWER_SERVICE); 719 boolean retval = pm.isPowerSaveMode(); 720 log("isPowerSaveModeOn=" + retval, true); 721 return retval; 722 } 723 724 /** 725 * @return Return true if the battery is currently considered to be charging. This means that 726 * the device is plugged in and is supplying sufficient power that the battery level is 727 * going up (or the battery is fully charged). 728 * See {@link android.os.BatteryManager#isCharging BatteryManager.isCharging()}. 729 */ isDeviceCharging()730 private boolean isDeviceCharging() { 731 final BatteryManager bm = (BatteryManager) mPhone.getContext().getSystemService( 732 Context.BATTERY_SERVICE); 733 boolean retval = bm.isCharging(); 734 log("isDeviceCharging=" + retval, true); 735 return retval; 736 } 737 738 /** 739 * @return True if one the device's screen (e.g. main screen, wifi display, HDMI display etc...) 740 * is on. 741 */ isScreenOn()742 private boolean isScreenOn() { 743 // Note that we don't listen to Intent.SCREEN_ON and Intent.SCREEN_OFF because they are no 744 // longer adequate for monitoring the screen state since they are not sent in cases where 745 // the screen is turned off transiently such as due to the proximity sensor. 746 final DisplayManager dm = (DisplayManager) mPhone.getContext().getSystemService( 747 Context.DISPLAY_SERVICE); 748 Display[] displays = dm.getDisplays(); 749 750 if (displays != null) { 751 for (Display display : displays) { 752 // Anything other than STATE_ON is treated as screen off, such as STATE_DOZE, 753 // STATE_DOZE_SUSPEND, etc... 754 if (display.getState() == Display.STATE_ON) { 755 log("Screen on for display=" + display, true); 756 return true; 757 } 758 } 759 log("Screens all off", true); 760 return false; 761 } 762 763 log("No displays found", true); 764 return false; 765 } 766 767 /** 768 * @return True if the radio is on. 769 */ isRadioOn()770 private boolean isRadioOn() { 771 return mPhone.isRadioOn(); 772 } 773 774 /** 775 * @return True if automotive projection (Android Auto) is active. 776 */ isAutomotiveProjectionActive()777 private boolean isAutomotiveProjectionActive() { 778 final UiModeManager umm = (UiModeManager) mPhone.getContext().getSystemService( 779 Context.UI_MODE_SERVICE); 780 if (umm == null) return false; 781 boolean isAutomotiveProjectionActive = (umm.getActiveProjectionTypes() 782 & PROJECTION_TYPE_AUTOMOTIVE) != 0; 783 log("isAutomotiveProjectionActive=" + isAutomotiveProjectionActive, true); 784 return isAutomotiveProjectionActive; 785 } 786 787 /** 788 * Register for PhysicalChannelConfig notifications changed. On change, msg.obj will be an 789 * AsyncResult with a boolean result. AsyncResult.result is true if notifications are enabled 790 * and false if they are disabled. 791 * 792 * @param h Handler to notify 793 * @param what msg.what when the message is delivered 794 * @param obj AsyncResult.userObj when the message is delivered 795 */ registerForPhysicalChannelConfigNotifChanged(Handler h, int what, Object obj)796 public void registerForPhysicalChannelConfigNotifChanged(Handler h, int what, Object obj) { 797 Registrant r = new Registrant(h, what, obj); 798 mPhysicalChannelConfigRegistrants.add(r); 799 } 800 801 /** 802 * Unregister for PhysicalChannelConfig notifications changed. 803 * @param h Handler to notify 804 */ unregisterForPhysicalChannelConfigNotifChanged(Handler h)805 public void unregisterForPhysicalChannelConfigNotifChanged(Handler h) { 806 mPhysicalChannelConfigRegistrants.remove(h); 807 } 808 809 /** 810 * Register a callback to decide whether signal strength should be notified or not. 811 * @param h Handler to notify 812 * @param what msg.what when the message is delivered 813 * @param obj AsyncResult.userObj when the message is delivered 814 */ registerForSignalStrengthReportDecision(Handler h, int what, Object obj)815 public void registerForSignalStrengthReportDecision(Handler h, int what, Object obj) { 816 Registrant r = new Registrant(h, what, obj); 817 mSignalStrengthReportDecisionCallbackRegistrants.add(r); 818 } 819 820 /** 821 * Unregister for Screen on, off notifications changed. 822 * @param h Handler to notify 823 */ unregisterForScreenStateChanged(Handler h)824 public void unregisterForScreenStateChanged(Handler h) { 825 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 826 Rlog.d(TAG, "unregisterForScreenStateChanged: carrierRoamingNbIotNtn is disabled"); 827 return; 828 } 829 830 mScreenStateRegistrants.remove(h); 831 } 832 833 /** 834 * Register a callback to receive the screen on or off. 835 * @param h Handler to notify 836 * @param what msg.what when the message is delivered 837 * @param obj AsyncResult.userObj when the message is delivered 838 */ registerForScreenStateChanged(Handler h, int what, Object obj)839 public void registerForScreenStateChanged(Handler h, int what, Object obj) { 840 if (!mFeatureFlags.carrierRoamingNbIotNtn()) { 841 Rlog.d(TAG, "registerForScreenStateChanged: carrierRoamingNbIotNtn is disabled"); 842 return; 843 } 844 Registrant r = new Registrant(h, what, obj); 845 mScreenStateRegistrants.add(r); 846 847 // Initial notification 848 mScreenStateRegistrants.notifyResult(mIsScreenOn); 849 } 850 851 /** 852 * Register a callback to decide whether signal strength should be notified or not. 853 * @param h Handler to notify 854 */ unregisterForSignalStrengthReportDecision(Handler h)855 public void unregisterForSignalStrengthReportDecision(Handler h) { 856 mSignalStrengthReportDecisionCallbackRegistrants.remove(h); 857 } 858 859 /** 860 * @param msg Debug message 861 * @param logIntoLocalLog True if log into the local log 862 */ log(String msg, boolean logIntoLocalLog)863 private void log(String msg, boolean logIntoLocalLog) { 864 if (DBG) Rlog.d(TAG, msg); 865 if (logIntoLocalLog) { 866 mLocalLog.log(msg); 867 } 868 } 869 870 /** 871 * Print the DeviceStateMonitor into the given stream. 872 * 873 * @param fd The raw file descriptor that the dump is being sent to. 874 * @param pw A PrintWriter to which the dump is to be set. 875 * @param args Additional arguments to the dump request. 876 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)877 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 878 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 879 ipw.increaseIndent(); 880 ipw.println("mIsTetheringOn=" + mIsTetheringOn); 881 ipw.println("mIsScreenOn=" + mIsScreenOn); 882 ipw.println("mIsCharging=" + mIsCharging); 883 ipw.println("mIsPowerSaveOn=" + mIsPowerSaveOn); 884 ipw.println("mIsLowDataExpected=" + mIsLowDataExpected); 885 ipw.println("mIsAutomotiveProjectionActive=" + mIsAutomotiveProjectionActive); 886 ipw.println("mUnsolicitedResponseFilter=" + mUnsolicitedResponseFilter); 887 ipw.println("mIsWifiConnected=" + mIsWifiConnected); 888 ipw.println("mIsAlwaysSignalStrengthReportingEnabled=" 889 + mIsAlwaysSignalStrengthReportingEnabled); 890 ipw.println("mIsRadioOn=" + mIsRadioOn); 891 ipw.println("Local logs:"); 892 ipw.increaseIndent(); 893 mLocalLog.dump(fd, ipw, args); 894 ipw.decreaseIndent(); 895 ipw.decreaseIndent(); 896 ipw.flush(); 897 } 898 899 /** 900 * Downlink reporting thresholds in kbps 901 * 902 * <p>Threshold values taken from FCC Speed Guide when available 903 * (https://www.fcc.gov/reports-research/guides/broadband-speed-guide) and Android WiFi speed 904 * labels (https://support.google.com/pixelphone/answer/2819519#strength_speed). 905 * 906 */ 907 private static final int[] LINK_CAPACITY_DOWNLINK_THRESHOLDS = new int[] { 908 100, // VoIP 909 500, // Web browsing 910 1000, // SD video streaming 911 5000, // HD video streaming 912 10000, // file downloading 913 20000, // 4K video streaming 914 50000, // LTE-Advanced speeds 915 75000, 916 100000, 917 200000, // 5G speeds 918 500000, 919 1000000, 920 1500000, 921 2000000 922 }; 923 924 /** Uplink reporting thresholds in kbps */ 925 private static final int[] LINK_CAPACITY_UPLINK_THRESHOLDS = new int[] { 926 100, // VoIP calls 927 500, 928 1000, // SD video calling 929 5000, // HD video calling 930 10000, // file uploading 931 20000, // 4K video calling 932 50000, 933 75000, 934 100000, 935 200000, 936 500000 937 }; 938 } 939