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

Commit 899d2af1 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Android (Google) Code Review
Browse files

Merge "Add a new WakeupMessage class and use it in two places."

parents c9bd275d 9d3aadb2
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.util;

import android.app.AlarmManager;
import android.content.Context;
import android.os.Handler;
import android.os.Message;

 /**
 * An AlarmListener that sends the specified message to a Handler and keeps the system awake until
 * the message is processed.
 *
 * This is useful when using the AlarmManager direct callback interface to wake up the system and
 * request that an object whose API consists of messages (such as a StateMachine) perform some
 * action.
 *
 * In this situation, using AlarmManager.onAlarmListener by itself will wake up the system to send
 * the message, but does not guarantee that the system will be awake until the target object has
 * processed it. This is because as soon as the onAlarmListener sends the message and returns, the
 * AlarmManager releases its wakelock and the system is free to go to sleep again.
 *
 */
public class WakeupMessage implements AlarmManager.OnAlarmListener {
    private static AlarmManager sAlarmManager;
    private final Handler mHandler;
    private final String mCmdName;
    private final int mCmd, mArg1, mArg2;

    public WakeupMessage(Context context, Handler handler,
            String cmdName, int cmd, int arg1, int arg2) {
        if (sAlarmManager == null) {
            sAlarmManager = context.getSystemService(AlarmManager.class);
        }
        mHandler = handler;
        mCmdName = cmdName;
        mCmd = cmd;
        mArg1 = arg1;
        mArg2 = arg2;
    }

    public WakeupMessage(Context context, Handler handler, String cmdName, int cmd, int arg1) {
        this(context, handler, cmdName, cmd, arg1, 0);
    }

    public WakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
        this(context, handler, cmdName, cmd, 0, 0);
    }

    public void schedule(long when) {
        sAlarmManager.setExact(
                AlarmManager.ELAPSED_REALTIME_WAKEUP, when, mCmdName, this, mHandler);
    }

    public void cancel() {
        sAlarmManager.cancel(this);
    }

    @Override
    public void onAlarm() {
        Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2);
        mHandler.handleMessage(msg);
        msg.recycle();
    }
}
+6 −13
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
import com.android.server.connectivity.NetworkAgentInfo;

import java.io.IOException;
@@ -565,19 +566,14 @@ public class NetworkMonitor extends StateMachine {
    private class LingeringState extends State {
        private static final String ACTION_LINGER_EXPIRED = "android.net.netmon.lingerExpired";

        private CustomIntentReceiver mBroadcastReceiver;
        private PendingIntent mIntent;
        private WakeupMessage mWakeupMessage;

        @Override
        public void enter() {
            mLingerToken = new Random().nextInt();
            mBroadcastReceiver = new CustomIntentReceiver(ACTION_LINGER_EXPIRED, mLingerToken,
                    CMD_LINGER_EXPIRED);
            mIntent = mBroadcastReceiver.getPendingIntent();
            final String cmdName = ACTION_LINGER_EXPIRED + "." + mNetworkAgentInfo.network.netId;
            mWakeupMessage = new WakeupMessage(mContext, getHandler(), cmdName, CMD_LINGER_EXPIRED);
            long wakeupTime = SystemClock.elapsedRealtime() + mLingerDelayMs;
            mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime,
                    // Give a specific window so we aren't subject to unknown inexactitude.
                    mLingerDelayMs / 6, mIntent);
            mWakeupMessage.schedule(wakeupTime);
        }

        @Override
@@ -592,8 +588,6 @@ public class NetworkMonitor extends StateMachine {
                    }
                    return NOT_HANDLED;
                case CMD_LINGER_EXPIRED:
                    if (message.arg1 != mLingerToken)
                        return HANDLED;
                    mConnectivityServiceHandler.sendMessage(
                            obtainMessage(EVENT_NETWORK_LINGER_COMPLETE, mNetworkAgentInfo));
                    return HANDLED;
@@ -624,8 +618,7 @@ public class NetworkMonitor extends StateMachine {

        @Override
        public void exit() {
            mAlarmManager.cancel(mIntent);
            mContext.unregisterReceiver(mBroadcastReceiver);
            mWakeupMessage.cancel();
        }
    }

+19 −43
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@ import com.android.internal.util.HexDump;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;

import android.app.AlarmManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -128,7 +128,6 @@ public class DhcpClient extends BaseDhcpStateMachine {

    // System services / libraries we use.
    private final Context mContext;
    private final AlarmManager mAlarmManager;
    private final Random mRandom;
    private final INetworkManagementService mNMService;

@@ -143,10 +142,10 @@ public class DhcpClient extends BaseDhcpStateMachine {

    // State variables.
    private final StateMachine mController;
    private final AlarmListener mKickAlarm;
    private final AlarmListener mTimeoutAlarm;
    private final AlarmListener mRenewAlarm;
    private final AlarmListener mOneshotTimeoutAlarm;
    private final WakeupMessage mKickAlarm;
    private final WakeupMessage mTimeoutAlarm;
    private final WakeupMessage mRenewAlarm;
    private final WakeupMessage mOneshotTimeoutAlarm;
    private final String mIfaceName;

    private boolean mRegisteredForPreDhcpNotification;
@@ -174,6 +173,11 @@ public class DhcpClient extends BaseDhcpStateMachine {
    private State mWaitBeforeStartState = new WaitBeforeStartState(mDhcpInitState);
    private State mWaitBeforeRenewalState = new WaitBeforeRenewalState(mDhcpRenewingState);

    private WakeupMessage makeWakeupMessage(String cmdName, int cmd) {
        cmdName = DhcpClient.class.getSimpleName() + "." + mIfaceName + "." + cmdName;
        return new WakeupMessage(mContext, getHandler(), cmdName, cmd);
    }

    private DhcpClient(Context context, StateMachine controller, String iface) {
        super(TAG);

@@ -197,22 +201,21 @@ public class DhcpClient extends BaseDhcpStateMachine {

        setInitialState(mStoppedState);

        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        mNMService = INetworkManagementService.Stub.asInterface(b);

        mRandom = new Random();

        // Used to schedule packet retransmissions.
        mKickAlarm = new AlarmListener("KICK", CMD_KICK);
        mKickAlarm = makeWakeupMessage("KICK", CMD_KICK);
        // Used to time out PacketRetransmittingStates.
        mTimeoutAlarm = new AlarmListener("TIMEOUT", CMD_TIMEOUT);
        mTimeoutAlarm = makeWakeupMessage("TIMEOUT", CMD_TIMEOUT);
        // Used to schedule DHCP renews.
        mRenewAlarm = new AlarmListener("RENEW", DhcpStateMachine.CMD_RENEW_DHCP);
        mRenewAlarm = makeWakeupMessage("RENEW", DhcpStateMachine.CMD_RENEW_DHCP);
        // Used to tell the caller when its request (CMD_START_DHCP or CMD_RENEW_DHCP) timed out.
        // TODO: when the legacy DHCP client is gone, make the client fully asynchronous and
        // remove this.
        mOneshotTimeoutAlarm = new AlarmListener("ONESHOT_TIMEOUT", CMD_ONESHOT_TIMEOUT);
        mOneshotTimeoutAlarm = makeWakeupMessage("ONESHOT_TIMEOUT", CMD_ONESHOT_TIMEOUT);
    }

    @Override
@@ -227,32 +230,6 @@ public class DhcpClient extends BaseDhcpStateMachine {
        return client;
    }

    /**
     * An AlarmListener that sends the specified command to the state machine.
     */
    private class AlarmListener implements AlarmManager.OnAlarmListener {
        private final int cmd;
        private final String name;

        public AlarmListener(final String cmdName, final int cmd) {
            this.cmd = cmd;
            this.name = DhcpClient.class.getSimpleName() + "." + mIfaceName + "." + cmdName;
        }

        public void set(long alarmTime) {
            mAlarmManager.setExact(
                    AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, name, this, getHandler());
        }

        public void cancel() {
            mAlarmManager.cancel(this);
        }

        public void onAlarm() {
            sendMessage(cmd);
        }
    }

    private boolean initInterface() {
        try {
            mIface = NetworkInterface.getByName(mIfaceName);
@@ -412,11 +389,11 @@ public class DhcpClient extends BaseDhcpStateMachine {
    }

    private void scheduleRenew() {
        mAlarmManager.cancel(mRenewAlarm);
        mRenewAlarm.cancel();
        if (mDhcpLeaseExpiry != 0) {
            long now = SystemClock.elapsedRealtime();
            long alarmTime = (now + mDhcpLeaseExpiry) / 2;
            mRenewAlarm.set(alarmTime);
            mRenewAlarm.schedule(alarmTime);
            Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s");
        } else {
            Log.d(TAG, "Infinite lease, no renewal needed");
@@ -548,7 +525,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
    // one state, so we can just use the state timeout.
    private void scheduleOneshotTimeout() {
        final long alarmTime = SystemClock.elapsedRealtime() + DHCP_TIMEOUT_MS;
        mOneshotTimeoutAlarm.set(alarmTime);
        mOneshotTimeoutAlarm.schedule(alarmTime);
    }

    class StoppedState extends LoggingState {
@@ -713,8 +690,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
            long now = SystemClock.elapsedRealtime();
            long timeout = jitterTimer(mTimer);
            long alarmTime = now + timeout;
            mKickAlarm.cancel();
            mKickAlarm.set(alarmTime);
            mKickAlarm.schedule(alarmTime);
            mTimer *= 2;
            if (mTimer > MAX_TIMEOUT_MS) {
                mTimer = MAX_TIMEOUT_MS;
@@ -724,7 +700,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
        protected void maybeInitTimeout() {
            if (mTimeout > 0) {
                long alarmTime = SystemClock.elapsedRealtime() + mTimeout;
                mTimeoutAlarm.set(alarmTime);
                mTimeoutAlarm.schedule(alarmTime);
            }
        }
    }