FileDocCategorySizeDatePackage
DhcpStateMachine.javaAPI DocAndroid 5.1 API15002Thu Mar 12 22:22:10 GMT 2015android.net

DhcpStateMachine

public class DhcpStateMachine extends com.android.internal.util.StateMachine
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: - 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) - A notification right before DHCP request or renewal is started. This can be used for any additional setup before DHCP. For example, wifi sets BT-Wifi coex settings right before DHCP is initiated
hide

Fields Summary
private static final String
TAG
private static final boolean
DBG
private com.android.internal.util.StateMachine
mController
private android.content.Context
mContext
private android.content.BroadcastReceiver
mBroadcastReceiver
private android.app.AlarmManager
mAlarmManager
private android.app.PendingIntent
mDhcpRenewalIntent
private PowerManager.WakeLock
mDhcpRenewWakeLock
private static final String
WAKELOCK_TAG
private android.net.DhcpResults
mDhcpResults
private static final int
DHCP_RENEW
private static final String
ACTION_DHCP_RENEW
private static final int
MIN_RENEWAL_TIME_SECS
private final String
mInterfaceName
private boolean
mRegisteredForPreDhcpNotification
private static final int
BASE
public static final int
CMD_START_DHCP
public static final int
CMD_STOP_DHCP
public static final int
CMD_RENEW_DHCP
public static final int
CMD_PRE_DHCP_ACTION
public static final int
CMD_POST_DHCP_ACTION
public static final int
CMD_ON_QUIT
public static final int
CMD_PRE_DHCP_ACTION_COMPLETE
public static final int
DHCP_SUCCESS
public static final int
DHCP_FAILURE
private com.android.internal.util.State
mDefaultState
private com.android.internal.util.State
mStoppedState
private com.android.internal.util.State
mWaitBeforeStartState
private com.android.internal.util.State
mRunningState
private com.android.internal.util.State
mWaitBeforeRenewalState
Constructors Summary
private DhcpStateMachine(android.content.Context context, com.android.internal.util.StateMachine controller, String intf)


           
        super(TAG);

        mContext = context;
        mController = controller;
        mInterfaceName = intf;

        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
        Intent dhcpRenewalIntent = new Intent(ACTION_DHCP_RENEW, null);
        mDhcpRenewalIntent = PendingIntent.getBroadcast(mContext, DHCP_RENEW, dhcpRenewalIntent, 0);

        PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
        mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
        mDhcpRenewWakeLock.setReferenceCounted(false);

        mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                //DHCP renew
                if (DBG) Log.d(TAG, "Sending a DHCP renewal " + this);
                //Lock released after 40s in worst case scenario
                mDhcpRenewWakeLock.acquire(40000);
                sendMessage(CMD_RENEW_DHCP);
            }
        };
        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_DHCP_RENEW));

        addState(mDefaultState);
            addState(mStoppedState, mDefaultState);
            addState(mWaitBeforeStartState, mDefaultState);
            addState(mRunningState, mDefaultState);
            addState(mWaitBeforeRenewalState, mDefaultState);

        setInitialState(mStoppedState);
    
Methods Summary
public voiddoQuit()
Quit the DhcpStateMachine.

hide

        quit();
    
public static android.net.DhcpStateMachinemakeDhcpStateMachine(android.content.Context context, com.android.internal.util.StateMachine controller, java.lang.String intf)

        DhcpStateMachine dsm = new DhcpStateMachine(context, controller, intf);
        dsm.start();
        return dsm;
    
protected voidonQuitting()

        mController.sendMessage(CMD_ON_QUIT);
    
public voidregisterForPreDhcpNotification()
This sends a notification right before DHCP request/renewal so that the controller can do certain actions before DHCP packets are sent out. When the controller is ready, it sends a CMD_PRE_DHCP_ACTION_COMPLETE message to indicate DHCP can continue This is used by Wifi at this time for the purpose of doing BT-Wifi coex handling during Dhcp

        mRegisteredForPreDhcpNotification = true;
    
private booleanrunDhcp(android.net.DhcpStateMachine$DhcpAction dhcpAction)

        boolean success = false;
        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 (success) {
            if (DBG) Log.d(TAG, "DHCP succeeded on " + mInterfaceName);
            long leaseDuration = dhcpResults.leaseDuration; //int to long conversion

            //Sanity check for renewal
            if (leaseDuration >= 0) {
                //TODO: would be good to notify the user that his network configuration is
                //bad and that the device cannot renew below MIN_RENEWAL_TIME_SECS
                if (leaseDuration < MIN_RENEWAL_TIME_SECS) {
                    leaseDuration = MIN_RENEWAL_TIME_SECS;
                }
                //Do it a bit earlier than half the lease duration time
                //to beat the native DHCP client and avoid extra packets
                //48% for one hour lease time = 29 minutes
                mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        SystemClock.elapsedRealtime() +
                        leaseDuration * 480, //in milliseconds
                        mDhcpRenewalIntent);
            } else {
                //infinite lease time, no renewal needed
            }

            mDhcpResults = dhcpResults;
            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpResults)
                .sendToTarget();
        } else {
            Log.e(TAG, "DHCP failed on " + mInterfaceName + ": " +
                    NetworkUtils.getDhcpError());
            NetworkUtils.stopDhcp(mInterfaceName);
            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
                .sendToTarget();
        }
        return success;