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