DhcpStateMachinepublic 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 |
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 void | doQuit()Quit the DhcpStateMachine.
quit();
| public static android.net.DhcpStateMachine | makeDhcpStateMachine(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 void | onQuitting()
mController.sendMessage(CMD_ON_QUIT);
| public void | registerForPreDhcpNotification()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 boolean | runDhcp(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;
|
|