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