• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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