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