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

Commit 34c6e6b8 authored by Erik Kline's avatar Erik Kline
Browse files

Add DhcpStateMachine PollingState.

This state leaves dhcpcd running and polls for results, with
exponential backoff to once every 32 seconds.

Bug: 19422416
Change-Id: I87f481969629ba104491f25ea36de1efc4ad105a
parent 3dda1fa4
Loading
Loading
Loading
Loading
+120 −57
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ import android.util.Log;
 * StateMachine that interacts with the native DHCP client and can talk to
 * a controller that also needs to be a StateMachine
 *
 * The Dhcp state machine provides the following features:
 * The DhcpStateMachine provides the following features:
 * - Wakeup and renewal using the native DHCP client  (which will not renew
 *   on its own when the device is in suspend state and this can lead to device
 *   holding IP address beyond expiry)
@@ -72,11 +72,6 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
    //Used for sanity check on setting up renewal
    private static final int MIN_RENEWAL_TIME_SECS = 5 * 60;  // 5 minutes

    private enum DhcpAction {
        START,
        RENEW
    };

    private final String mInterfaceName;
    private boolean mRegisteredForPreDhcpNotification = false;

@@ -99,6 +94,9 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
     * after pre DHCP action is complete */
    public static final int CMD_PRE_DHCP_ACTION_COMPLETE    = BASE + 7;

    /* Command from ourselves to see if DHCP results are available */
    private static final int CMD_GET_DHCP_RESULTS           = BASE + 8;

    /* Message.arg1 arguments to CMD_POST_DHCP notification */
    public static final int DHCP_SUCCESS = 1;
    public static final int DHCP_FAILURE = 2;
@@ -108,6 +106,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
    private State mWaitBeforeStartState = new WaitBeforeStartState();
    private State mRunningState = new RunningState();
    private State mWaitBeforeRenewalState = new WaitBeforeRenewalState();
    private State mPollingState = new PollingState();

    private DhcpStateMachine(Context context, StateMachine controller, String intf) {
        super(TAG);
@@ -139,6 +138,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
        addState(mDefaultState);
            addState(mStoppedState, mDefaultState);
            addState(mWaitBeforeStartState, mDefaultState);
            addState(mPollingState, mDefaultState);
            addState(mRunningState, mDefaultState);
            addState(mWaitBeforeRenewalState, mDefaultState);

@@ -206,6 +206,10 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
        @Override
        public void enter() {
            if (DBG) Log.d(TAG, getName() + "\n");
            if (!NetworkUtils.stopDhcp(mInterfaceName)) {
                Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
            }
            mDhcpResults = null;
        }

        @Override
@@ -219,7 +223,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
                        mController.sendMessage(CMD_PRE_DHCP_ACTION);
                        transitionTo(mWaitBeforeStartState);
                    } else {
                        if (runDhcp(DhcpAction.START)) {
                        if (runDhcpStart()) {
                            transitionTo(mRunningState);
                        }
                    }
@@ -247,10 +251,10 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
            switch (message.what) {
                case CMD_PRE_DHCP_ACTION_COMPLETE:
                    if (runDhcp(DhcpAction.START)) {
                    if (runDhcpStart()) {
                        transitionTo(mRunningState);
                    } else {
                        transitionTo(mStoppedState);
                        transitionTo(mPollingState);
                    }
                    break;
                case CMD_STOP_DHCP:
@@ -267,6 +271,55 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
        }
    }

    class PollingState extends State {
        private static final long MAX_DELAY_SECONDS = 32;
        private long delaySeconds;

        private void scheduleNextResultsCheck() {
            sendMessageDelayed(obtainMessage(CMD_GET_DHCP_RESULTS), delaySeconds * 1000);
            delaySeconds *= 2;
            if (delaySeconds > MAX_DELAY_SECONDS) {
                delaySeconds = MAX_DELAY_SECONDS;
            }
        }

        @Override
        public void enter() {
            if (DBG) Log.d(TAG, "Entering " + getName() + "\n");
            delaySeconds = 1;
            scheduleNextResultsCheck();
        }

        @Override
        public boolean processMessage(Message message) {
            boolean retValue = HANDLED;
            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
            switch (message.what) {
                case CMD_GET_DHCP_RESULTS:
                    if (DBG) Log.d(TAG, "GET_DHCP_RESULTS on " + mInterfaceName);
                    if (dhcpSucceeded()) {
                        transitionTo(mRunningState);
                    } else {
                        scheduleNextResultsCheck();
                    }
                    break;
                case CMD_STOP_DHCP:
                    transitionTo(mStoppedState);
                    break;
                default:
                    retValue = NOT_HANDLED;
                    break;
            }
            return retValue;
        }

        @Override
        public void exit() {
            if (DBG) Log.d(TAG, "Exiting " + getName() + "\n");
            removeMessages(CMD_GET_DHCP_RESULTS);
        }
    }

    class RunningState extends State {
        @Override
        public void enter() {
@@ -280,9 +333,6 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
            switch (message.what) {
                case CMD_STOP_DHCP:
                    mAlarmManager.cancel(mDhcpRenewalIntent);
                    if (!NetworkUtils.stopDhcp(mInterfaceName)) {
                        Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
                    }
                    transitionTo(mStoppedState);
                    break;
                case CMD_RENEW_DHCP:
@@ -292,7 +342,7 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
                        transitionTo(mWaitBeforeRenewalState);
                        //mDhcpRenewWakeLock is released in WaitBeforeRenewalState
                    } else {
                        if (!runDhcp(DhcpAction.RENEW)) {
                        if (!runDhcpRenew()) {
                            transitionTo(mStoppedState);
                        }
                        mDhcpRenewWakeLock.release();
@@ -321,13 +371,10 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
            switch (message.what) {
                case CMD_STOP_DHCP:
                    mAlarmManager.cancel(mDhcpRenewalIntent);
                    if (!NetworkUtils.stopDhcp(mInterfaceName)) {
                        Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
                    }
                    transitionTo(mStoppedState);
                    break;
                case CMD_PRE_DHCP_ACTION_COMPLETE:
                    if (runDhcp(DhcpAction.RENEW)) {
                    if (runDhcpRenew()) {
                       transitionTo(mRunningState);
                    } else {
                       transitionTo(mStoppedState);
@@ -348,22 +395,13 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
        }
    }

    private boolean runDhcp(DhcpAction dhcpAction) {
        boolean success = false;
    private boolean dhcpSucceeded() {
        DhcpResults dhcpResults = new DhcpResults();

        if (dhcpAction == DhcpAction.START) {
            /* Stop any existing DHCP daemon before starting new */
            NetworkUtils.stopDhcp(mInterfaceName);
            if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
            success = NetworkUtils.runDhcp(mInterfaceName, dhcpResults);
        } else if (dhcpAction == DhcpAction.RENEW) {
            if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName);
            success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpResults);
            if (success) dhcpResults.updateFromDhcpRequest(mDhcpResults);
        if (!NetworkUtils.getDhcpResults(mInterfaceName, dhcpResults)) {
            return false;
        }
        if (success) {
            if (DBG) Log.d(TAG, "DHCP succeeded on " + mInterfaceName);

        if (DBG) Log.d(TAG, "DHCP results found for " + mInterfaceName);
        long leaseDuration = dhcpResults.leaseDuration; //int to long conversion

        //Sanity check for renewal
@@ -384,16 +422,41 @@ public class DhcpStateMachine extends BaseDhcpStateMachine {
            //infinite lease time, no renewal needed
        }

        // Fill in any missing fields in dhcpResults from the previous results.
        // If mDhcpResults is null (i.e. this is the first server response),
        // this is a noop.
        dhcpResults.updateFromDhcpRequest(mDhcpResults);
        mDhcpResults = dhcpResults;
        mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpResults)
            .sendToTarget();
        } else {
            Log.e(TAG, "DHCP failed on " + mInterfaceName + ": " +
                    NetworkUtils.getDhcpError());
        return true;
    }

    private boolean runDhcpStart() {
        /* Stop any existing DHCP daemon before starting new */
        NetworkUtils.stopDhcp(mInterfaceName);
        mDhcpResults = null;

        if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
        if (!NetworkUtils.startDhcp(mInterfaceName) || !dhcpSucceeded()) {
            Log.e(TAG, "DHCP request failed on " + mInterfaceName + ": " +
                    NetworkUtils.getDhcpError());
            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
                    .sendToTarget();
            return false;
        }
        return true;
    }

    private boolean runDhcpRenew() {
        if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName);
        if (!NetworkUtils.startDhcpRenew(mInterfaceName) || !dhcpSucceeded()) {
            Log.e(TAG, "DHCP renew failed on " + mInterfaceName + ": " +
                    NetworkUtils.getDhcpError());
            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
                    .sendToTarget();
            return false;
        }
        return success;
        return true;
    }
}