Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15bfd2f5 authored by Nathan Harold's avatar Nathan Harold Committed by android-build-merger
Browse files

Merge "Add CellInfo Rate Limiting to DeviceStateMonitor"

am: f3c2a7d2

Change-Id: I9a07b46e4e91658e7c9176bcdd4723c2b2a94ab8
parents bb3a64b0 f3c2a7d2
Loading
Loading
Loading
Loading
+119 −7
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ import android.content.IntentFilter;
import android.hardware.display.DisplayManager;
import android.hardware.radio.V1_2.IndicationFilter;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Message;
@@ -39,11 +42,14 @@ import android.util.LocalLog;
import android.util.SparseIntArray;
import android.view.Display;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * The device state monitor monitors the device state such as charging state, power saving sate,
@@ -58,21 +64,65 @@ public class DeviceStateMonitor extends Handler {
    protected static final boolean DBG = false;      /* STOPSHIP if true */
    protected static final String TAG = DeviceStateMonitor.class.getSimpleName();

    private static final int EVENT_RIL_CONNECTED                = 0;
    private static final int EVENT_UPDATE_MODE_CHANGED          = 1;
    private static final int EVENT_SCREEN_STATE_CHANGED         = 2;
    private static final int EVENT_POWER_SAVE_MODE_CHANGED      = 3;
    private static final int EVENT_CHARGING_STATE_CHANGED       = 4;
    private static final int EVENT_TETHERING_STATE_CHANGED      = 5;
    private static final int EVENT_RADIO_AVAILABLE              = 6;
    static final int EVENT_RIL_CONNECTED                = 0;
    static final int EVENT_UPDATE_MODE_CHANGED          = 1;
    @VisibleForTesting
    static final int EVENT_SCREEN_STATE_CHANGED         = 2;
    static final int EVENT_POWER_SAVE_MODE_CHANGED      = 3;
    @VisibleForTesting
    static final int EVENT_CHARGING_STATE_CHANGED       = 4;
    static final int EVENT_TETHERING_STATE_CHANGED      = 5;
    static final int EVENT_RADIO_AVAILABLE              = 6;
    @VisibleForTesting
    static final int EVENT_WIFI_CONNECTION_CHANGED      = 7;

    // TODO(b/74006656) load hysteresis values from a property when DeviceStateMonitor starts
    private static final int HYSTERESIS_KBPS = 50;

    private static final int WIFI_UNAVAILABLE = 0;
    private static final int WIFI_AVAILABLE = 1;

    private final Phone mPhone;

    private final LocalLog mLocalLog = new LocalLog(100);

    private final NetworkRequest mWifiNetworkRequest =
            new NetworkRequest.Builder()
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
            .build();

    private final ConnectivityManager.NetworkCallback mNetworkCallback =
            new ConnectivityManager.NetworkCallback() {
        Set<Network> mWifiNetworks = new HashSet<>();

        @Override
        public void onAvailable(Network network) {
            synchronized (mWifiNetworks) {
                if (mWifiNetworks.size() == 0) {
                    // We just connected to Wifi, so send an update.
                    obtainMessage(EVENT_WIFI_CONNECTION_CHANGED, WIFI_AVAILABLE, 0).sendToTarget();
                    log("Wifi (default) connected", true);
                }
                mWifiNetworks.add(network);
            }
        }

        @Override
        public void onLost(Network network) {
            synchronized (mWifiNetworks) {
                mWifiNetworks.remove(network);
                if (mWifiNetworks.size() == 0) {
                    // We just disconnected from the last connected wifi, so send an update.
                    obtainMessage(
                            EVENT_WIFI_CONNECTION_CHANGED, WIFI_UNAVAILABLE, 0).sendToTarget();
                    log("Wifi (default) disconnected", true);
                }
            }
        }
    };

    /**
     * Flag for wifi/usb/bluetooth tethering turned on or not
     */
@@ -105,6 +155,22 @@ public class DeviceStateMonitor extends Handler {
     */
    private boolean mIsLowDataExpected;

    /**
     * Wifi is connected. True means both that cellular is likely to be asleep when the screen is
     * on and that in most cases the device location is relatively close to the WiFi AP. This means
     * that fewer location updates should be provided by cellular.
     */
    private boolean mIsWifiConnected;

    @VisibleForTesting
    static final int CELL_INFO_INTERVAL_SHORT_MS = 2000;
    @VisibleForTesting
    static final int CELL_INFO_INTERVAL_LONG_MS = 10000;

    /** The minimum required wait time between cell info requests to the modem */
    private int mCellInfoMinInterval = CELL_INFO_INTERVAL_SHORT_MS;


    private SparseIntArray mUpdateModes = new SparseIntArray();

    /**
@@ -202,6 +268,10 @@ public class DeviceStateMonitor extends Handler {

        mPhone.mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
        mPhone.mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);

        ConnectivityManager cm = (ConnectivityManager) phone.getContext().getSystemService(
                Context.CONNECTIVITY_SERVICE);
        cm.registerNetworkCallback(mWifiNetworkRequest, mNetworkCallback);
    }

    /**
@@ -211,6 +281,27 @@ public class DeviceStateMonitor extends Handler {
        return !mIsCharging && !mIsTetheringOn && !mIsScreenOn;
    }

    /**
     * @return The minimum period between CellInfo requests to the modem
     */
    @VisibleForTesting
    public int computeCellInfoMinInterval() {
        // The screen is on and we're either on cellular or charging. Screen on + Charging is
        // a likely vehicular scenario, even if there is a nomadic AP.
        if (mIsScreenOn && !mIsWifiConnected) {
            // Screen on without WiFi - We are in a high power likely mobile situation.
            return CELL_INFO_INTERVAL_SHORT_MS;
        } else if (mIsScreenOn && mIsCharging) {
            // Screen is on and we're charging, so we favor accuracy over power.
            return CELL_INFO_INTERVAL_SHORT_MS;
        } else {
            // If the screen is off, apps should not need cellular location at rapid intervals.
            // If the screen is on but we are on wifi and not charging then cellular location
            // accuracy is not crucial, so favor modem power saving over high accuracy.
            return CELL_INFO_INTERVAL_LONG_MS;
        }
    }

    /**
     * @return True if signal strength update should be turned off.
     */
@@ -358,6 +449,9 @@ public class DeviceStateMonitor extends Handler {
            case EVENT_TETHERING_STATE_CHANGED:
                onUpdateDeviceState(msg.what, msg.arg1 != 0);
                break;
            case EVENT_WIFI_CONNECTION_CHANGED:
                onUpdateDeviceState(msg.what, msg.arg1 != WIFI_UNAVAILABLE);
                break;
            default:
                throw new IllegalStateException("Unexpected message arrives. msg = " + msg.what);
        }
@@ -388,11 +482,23 @@ public class DeviceStateMonitor extends Handler {
                if (mIsPowerSaveOn == state) return;
                mIsPowerSaveOn = state;
                sendDeviceState(POWER_SAVE_MODE, mIsPowerSaveOn);
                break;
            case EVENT_WIFI_CONNECTION_CHANGED:
                if (mIsWifiConnected == state) return;
                mIsWifiConnected = state;

                break;
            default:
                return;
        }

        final int newCellInfoMinInterval = computeCellInfoMinInterval();
        if (mCellInfoMinInterval != newCellInfoMinInterval) {
            mCellInfoMinInterval = newCellInfoMinInterval;
            setCellInfoMinInterval(mCellInfoMinInterval);
            log("CellInfo Min Interval Updated to " + newCellInfoMinInterval, true);
        }

        if (mIsLowDataExpected != isLowDataExpected()) {
            mIsLowDataExpected = !mIsLowDataExpected;
            sendDeviceState(LOW_DATA_EXPECTED, mIsLowDataExpected);
@@ -437,6 +543,7 @@ public class DeviceStateMonitor extends Handler {
        setUnsolResponseFilter(mUnsolicitedResponseFilter, true);
        setSignalStrengthReportingCriteria();
        setLinkCapacityReportingCriteria();
        setCellInfoMinInterval(mCellInfoMinInterval);
    }

    /**
@@ -501,6 +608,10 @@ public class DeviceStateMonitor extends Handler {
                LINK_CAPACITY_UPLINK_THRESHOLDS, AccessNetworkType.CDMA2000);
    }

    private void setCellInfoMinInterval(int rate) {
        mPhone.setCellInfoMinInterval(rate);
    }

    /**
     * @return True if the device is currently in power save mode.
     * See {@link android.os.BatteryManager#isPowerSaveMode BatteryManager.isPowerSaveMode()}.
@@ -579,6 +690,7 @@ public class DeviceStateMonitor extends Handler {
        ipw.println("mIsPowerSaveOn=" + mIsPowerSaveOn);
        ipw.println("mIsLowDataExpected=" + mIsLowDataExpected);
        ipw.println("mUnsolicitedResponseFilter=" + mUnsolicitedResponseFilter);
        ipw.println("mIsWifiConnected=" + mIsWifiConnected);
        ipw.println("Local logs:");
        ipw.increaseIndent();
        mLocalLog.dump(fd, ipw, args);
+5 −0
Original line number Diff line number Diff line
@@ -1722,6 +1722,11 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        return (r != null) ? r.getRecordsLoaded() : false;
    }

    /** Set the minimum interval for CellInfo requests to the modem */
    public void setCellInfoMinInterval(int interval) {
        getServiceStateTracker().setCellInfoMinInterval(interval);
    }

    /**
     * @return the last known CellInfo
     */
+0 −4
Original line number Diff line number Diff line
@@ -3138,10 +3138,6 @@ public class RIL extends BaseCommands implements CommandsInterface {
        }
    }

    void setCellInfoListRate() {
        setCellInfoListRate(Integer.MAX_VALUE, null, mRILDefaultWorkSource);
    }

    @Override
    public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, Message result) {

+0 −1
Original line number Diff line number Diff line
@@ -672,7 +672,6 @@ public class RadioIndication extends IRadioIndication.Stub {
        // Initial conditions
        mRil.setRadioPower(false, null);
        mRil.setCdmaSubscriptionSource(mRil.mCdmaSubscription, null);
        mRil.setCellInfoListRate();
        // todo: this should not require a version number now. Setting it to latest RIL version for
        // now.
        mRil.notifyRegistrantsRilConnectionChanged(15);
+9 −3
Original line number Diff line number Diff line
@@ -128,13 +128,13 @@ public class ServiceStateTracker extends Handler {
    private ServiceState mNewSS;

    // This is the minimum interval at which CellInfo requests will be serviced by the modem.
    // Any requests that arrive within MAX_AGE of the previous reuqest will simply receive the
    // Any requests that arrive within MinInterval of the previous reuqest will simply receive the
    // cached result. This is a power-saving feature, because requests to the modem may require
    // wakeup of a separate chip and bus communication. Because the cost of wakeups is
    // architecture dependent, it would be preferable if this sort of optimization could be
    // handled in SoC-specific code, but for now, keep it here to ensure that in case further
    // optimizations are not present elsewhere, there is a power-management scheme of last resort.
    private static final long LAST_CELL_INFO_LIST_MAX_AGE_MS = 2000;
    private int mCellInfoMinIntervalMs =  2000;

    // Maximum time to wait for a CellInfo request before assuming it won't arrive and returning
    // null to callers. Note, that if a CellInfo response does arrive later, then it will be
@@ -4354,6 +4354,11 @@ public class ServiceStateTracker extends Handler {
        return mLastCellInfoList;
    }

    /** Set the minimum time between CellInfo requests to the modem, in milliseconds */
    public void setCellInfoMinInterval(int interval) {
        mCellInfoMinIntervalMs = interval;
    }

    /**
     * Request the latest CellInfo from the modem.
     *
@@ -4381,7 +4386,7 @@ public class ServiceStateTracker extends Handler {
            // Check to see whether the elapsed time is sufficient for a new request; if not, then
            // return the result of the last request (if expected).
            final long curTime = SystemClock.elapsedRealtime();
            if ((curTime - mLastCellInfoReqTime) < LAST_CELL_INFO_LIST_MAX_AGE_MS) {
            if ((curTime - mLastCellInfoReqTime) < mCellInfoMinIntervalMs) {
                if (rspMsg != null) {
                    if (DBG) log("SST.requestAllCellInfo(): return last, back to back calls");
                    AsyncResult.forMessage(rspMsg, mLastCellInfoList, null);
@@ -4563,6 +4568,7 @@ public class ServiceStateTracker extends Handler {
        pw.println(" mDeviceShuttingDown=" + mDeviceShuttingDown);
        pw.println(" mSpnUpdatePending=" + mSpnUpdatePending);
        pw.println(" mLteRsrpBoost=" + mLteRsrpBoost);
        pw.println(" mCellInfoMinIntervalMs=" + mCellInfoMinIntervalMs);
        dumpEarfcnPairList(pw);

        mLocaleTracker.dump(fd, pw, args);
Loading