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