18bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti/*
28bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * Copyright (C) 2015 The Android Open Source Project
38bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti *
48bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License");
58bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * you may not use this file except in compliance with the License.
68bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * You may obtain a copy of the License at
78bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti *
88bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti *      http://www.apache.org/licenses/LICENSE-2.0
98bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti *
108bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * Unless required by applicable law or agreed to in writing, software
118bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS,
128bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * See the License for the specific language governing permissions and
148bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * limitations under the License.
158bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti */
168bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
178bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittipackage com.android.server.connectivity;
188bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
198bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport com.android.internal.util.HexDump;
208bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport com.android.internal.util.IndentingPrintWriter;
218bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport com.android.server.connectivity.KeepalivePacketData;
228bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport com.android.server.connectivity.NetworkAgentInfo;
238bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.net.ConnectivityManager;
248bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.net.ConnectivityManager.PacketKeepalive;
258bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.net.LinkAddress;
268bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.net.NetworkAgent;
278bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.net.NetworkUtils;
288bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.net.util.IpUtils;
298bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.os.Binder;
308bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.os.IBinder;
318bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.os.Handler;
328bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.os.Message;
338bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.os.Messenger;
348bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.os.Process;
358bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.os.RemoteException;
368bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.system.OsConstants;
378bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.util.Log;
388bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport android.util.Pair;
398bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
408bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport java.nio.ByteBuffer;
418bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport java.nio.ByteOrder;
428bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport java.net.Inet4Address;
438bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport java.net.Inet6Address;
448bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport java.net.InetAddress;
458bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport java.util.ArrayList;
468bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport java.util.HashMap;
478bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
488bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport static android.net.ConnectivityManager.PacketKeepalive.*;
498bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport static android.net.NetworkAgent.CMD_START_PACKET_KEEPALIVE;
508bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport static android.net.NetworkAgent.CMD_STOP_PACKET_KEEPALIVE;
518bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittiimport static android.net.NetworkAgent.EVENT_PACKET_KEEPALIVE;
528bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
538bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti/**
548bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * Manages packet keepalive requests.
558bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti *
568bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * Provides methods to stop and start keepalive requests, and keeps track of keepalives across all
578bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * networks. This class is tightly coupled to ConnectivityService. It is not thread-safe and its
588bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti * methods must be called only from the ConnectivityService handler thread.
598bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti */
608bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colittipublic class KeepaliveTracker {
618bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
628bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    private static final String TAG = "KeepaliveTracker";
6312acbd7836e989150d73b04452d8ee300d54bcf6Joe Onorato    private static final boolean DBG = false;
648bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
65b9884663124b609a5cb093fc4a8a8a3b9a8d308dLorenzo Colitti    public static final String PERMISSION = android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
668bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
678bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    /** Keeps track of keepalive requests. */
688bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    private final HashMap <NetworkAgentInfo, HashMap<Integer, KeepaliveInfo>> mKeepalives =
698bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            new HashMap<> ();
708bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    private final Handler mConnectivityServiceHandler;
718bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
728bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public KeepaliveTracker(Handler handler) {
738bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        mConnectivityServiceHandler = handler;
748bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
758bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
768bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    /**
778bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti     * Tracks information about a packet keepalive.
788bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti     *
798bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti     * All information about this keepalive is known at construction time except the slot number,
808bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti     * which is only returned when the hardware has successfully started the keepalive.
818bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti     */
828bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    class KeepaliveInfo implements IBinder.DeathRecipient {
838bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        // Bookkeping data.
848bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private final Messenger mMessenger;
858bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private final IBinder mBinder;
868bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private final int mUid;
878bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private final int mPid;
888bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private final NetworkAgentInfo mNai;
898bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
908bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        /** Keepalive slot. A small integer that identifies this keepalive among the ones handled
918bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti          * by this network. */
928bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private int mSlot = PacketKeepalive.NO_KEEPALIVE;
938bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
948bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        // Packet data.
958bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private final KeepalivePacketData mPacket;
968bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private final int mInterval;
978bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
988bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        // Whether the keepalive is started or not.
998bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        public boolean isStarted;
1008bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1018bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        public KeepaliveInfo(Messenger messenger, IBinder binder, NetworkAgentInfo nai,
1028bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                KeepalivePacketData packet, int interval) {
1038bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mMessenger = messenger;
1048bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mBinder = binder;
1058bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mPid = Binder.getCallingPid();
1068bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mUid = Binder.getCallingUid();
1078bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1088bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mNai = nai;
1098bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mPacket = packet;
1108bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mInterval = interval;
1118bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1128bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            try {
1138bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                mBinder.linkToDeath(this, 0);
1148bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            } catch (RemoteException e) {
1158bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                binderDied();
1168bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
1178bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1188bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1198bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        public NetworkAgentInfo getNai() {
1208bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return mNai;
1218bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1228bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1238bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        public String toString() {
1248bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return new StringBuffer("KeepaliveInfo [")
1258bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(" network=").append(mNai.network)
1268bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(" isStarted=").append(isStarted)
1278bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(" ")
1288bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(IpUtils.addressAndPortToString(mPacket.srcAddress, mPacket.srcPort))
1298bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append("->")
1308bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort))
1318bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(" interval=" + mInterval)
1328bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(" data=" + HexDump.toHexString(mPacket.data))
1338bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(" uid=").append(mUid).append(" pid=").append(mPid)
1348bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .append(" ]")
1358bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    .toString();
1368bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1378bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1388bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        /** Sends a message back to the application via its PacketKeepalive.Callback. */
1398bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        void notifyMessenger(int slot, int err) {
1408bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            KeepaliveTracker.this.notifyMessenger(mMessenger, slot, err);
1418bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1428bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1438bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        /** Called when the application process is killed. */
1448bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        public void binderDied() {
1458bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            // Not called from ConnectivityService handler thread, so send it a message.
1468bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mConnectivityServiceHandler.obtainMessage(
1478bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    NetworkAgent.CMD_STOP_PACKET_KEEPALIVE,
1488bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    mSlot, PacketKeepalive.BINDER_DIED, mNai.network).sendToTarget();
1498bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1508bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1518bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        void unlinkDeathRecipient() {
1528bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (mBinder != null) {
1538bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                mBinder.unlinkToDeath(this, 0);
1548bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
1558bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1568bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1578bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private int checkNetworkConnected() {
1588bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (!mNai.networkInfo.isConnectedOrConnecting()) {
1598bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                return ERROR_INVALID_NETWORK;
1608bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
1618bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return SUCCESS;
1628bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1638bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1648bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private int checkSourceAddress() {
1658bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            // Check that we have the source address.
1668bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            for (InetAddress address : mNai.linkProperties.getAddresses()) {
1678bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                if (address.equals(mPacket.srcAddress)) {
1688bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    return SUCCESS;
1698bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                }
1708bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
1718bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return ERROR_INVALID_IP_ADDRESS;
1728bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1738bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1748bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private int checkInterval() {
1758bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return mInterval >= 20 ? SUCCESS : ERROR_INVALID_INTERVAL;
1768bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1778bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1788bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        private int isValid() {
1798bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            synchronized (mNai) {
1808bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                int error = checkInterval();
1818bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                if (error == SUCCESS) error = checkNetworkConnected();
1828bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                if (error == SUCCESS) error = checkSourceAddress();
1838bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                return error;
1848bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
1858bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1868bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1878bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        void start(int slot) {
1888bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            int error = isValid();
1898bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (error == SUCCESS) {
1908bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                mSlot = slot;
1918bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.name());
1928bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                mNai.asyncChannel.sendMessage(CMD_START_PACKET_KEEPALIVE, slot, mInterval, mPacket);
1938bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            } else {
1948bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                notifyMessenger(NO_KEEPALIVE, error);
1958bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                return;
1968bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
1978bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
1988bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
1998bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        void stop(int reason) {
2008bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            int uid = Binder.getCallingUid();
2018bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (uid != mUid && uid != Process.SYSTEM_UID) {
2028bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                if (DBG) {
2038bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
2048bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                }
2058bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
2068bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (isStarted) {
2078bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
2088bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                mNai.asyncChannel.sendMessage(CMD_STOP_PACKET_KEEPALIVE, mSlot);
2098bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
2109acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti            // TODO: at the moment we unconditionally return failure here. In cases where the
2119acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti            // NetworkAgent is alive, should we ask it to reply, so it can return failure?
2128bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            notifyMessenger(mSlot, reason);
2138bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            unlinkDeathRecipient();
2148bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2158bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
2168bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
2178bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    void notifyMessenger(Messenger messenger, int slot, int err) {
2188bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        Message message = Message.obtain();
2198bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        message.what = EVENT_PACKET_KEEPALIVE;
2208bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        message.arg1 = slot;
2218bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        message.arg2 = err;
2228bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        message.obj = null;
2238bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        try {
2248bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            messenger.send(message);
2258bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        } catch (RemoteException e) {
2268bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            // Process died?
2278bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2288bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
2298bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
2308bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    private  int findFirstFreeSlot(NetworkAgentInfo nai) {
2318bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        HashMap networkKeepalives = mKeepalives.get(nai);
2328bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (networkKeepalives == null) {
2338bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            networkKeepalives = new HashMap<Integer, KeepaliveInfo>();
2348bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mKeepalives.put(nai, networkKeepalives);
2358bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2368bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
2379acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti        // Find the lowest-numbered free slot. Slot numbers start from 1, because that's what two
2389acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti        // separate chipset implementations independently came up with.
2398bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        int slot;
2409acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti        for (slot = 1; slot <= networkKeepalives.size(); slot++) {
2418bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (networkKeepalives.get(slot) == null) {
2428bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                return slot;
2438bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
2448bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2458bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        return slot;
2468bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
2478bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
2488bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public void handleStartKeepalive(Message message) {
2498bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        KeepaliveInfo ki = (KeepaliveInfo) message.obj;
2508bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        NetworkAgentInfo nai = ki.getNai();
2518bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        int slot = findFirstFreeSlot(nai);
2528bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        mKeepalives.get(nai).put(slot, ki);
2538bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        ki.start(slot);
2548bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
2558bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
2568bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
2578bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
2588bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (networkKeepalives != null) {
2598bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            for (KeepaliveInfo ki : networkKeepalives.values()) {
2608bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                ki.stop(reason);
2618bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
2628bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            networkKeepalives.clear();
2638bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mKeepalives.remove(nai);
2648bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2658bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
2668bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
2678bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) {
2689acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti        String networkName = (nai == null) ? "(null)" : nai.name();
2698bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
2708bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (networkKeepalives == null) {
2719acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti            Log.e(TAG, "Attempt to stop keepalive on nonexistent network " + networkName);
2728bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return;
2738bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2748bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        KeepaliveInfo ki = networkKeepalives.get(slot);
2758bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (ki == null) {
2769acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti            Log.e(TAG, "Attempt to stop nonexistent keepalive " + slot + " on " + networkName);
2778bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return;
2788bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2798bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        ki.stop(reason);
2808bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        networkKeepalives.remove(slot);
2818bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (networkKeepalives.isEmpty()) {
2828bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            mKeepalives.remove(nai);
2838bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
2848bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
2858bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
2868bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public void handleCheckKeepalivesStillValid(NetworkAgentInfo nai) {
2878bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
2888bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (networkKeepalives != null) {
2898bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            ArrayList<Pair<Integer, Integer>> invalidKeepalives = new ArrayList<>();
2908bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            for (int slot : networkKeepalives.keySet()) {
2918bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                int error = networkKeepalives.get(slot).isValid();
2928bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                if (error != SUCCESS) {
2938bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    invalidKeepalives.add(Pair.create(slot, error));
2948bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                }
2958bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
2968bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            for (Pair<Integer, Integer> slotAndError: invalidKeepalives) {
2978bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                handleStopKeepalive(nai, slotAndError.first, slotAndError.second);
2988bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
2998bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
3008bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
3018bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
3028bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public void handleEventPacketKeepalive(NetworkAgentInfo nai, Message message) {
3038bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        int slot = message.arg1;
3048bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        int reason = message.arg2;
3058bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
3068bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        KeepaliveInfo ki = null;
3078bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        try {
3088bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            ki = mKeepalives.get(nai).get(slot);
3098bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        } catch(NullPointerException e) {}
3108bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (ki == null) {
3118bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            Log.e(TAG, "Event for unknown keepalive " + slot + " on " + nai.name());
3128bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return;
3138bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
3148bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
3158bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        if (reason == SUCCESS && !ki.isStarted) {
3168bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            // Keepalive successfully started.
3178bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
3188bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            ki.isStarted = true;
3198bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            ki.notifyMessenger(slot, reason);
3208bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        } else {
3218bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            // Keepalive successfully stopped, or error.
3228bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            ki.isStarted = false;
3238bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            if (reason == SUCCESS) {
3248bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                if (DBG) Log.d(TAG, "Successfully stopped keepalive " + slot + " on " + nai.name());
3258bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            } else {
3268bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                if (DBG) Log.d(TAG, "Keepalive " + slot + " on " + nai.name() + " error " + reason);
3278bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
3288bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            handleStopKeepalive(nai, slot, reason);
3298bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
3308bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
3318bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
3328bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public void startNattKeepalive(NetworkAgentInfo nai, int intervalSeconds, Messenger messenger,
3338bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            IBinder binder, String srcAddrString, int srcPort, String dstAddrString, int dstPort) {
3349acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti        if (nai == null) {
3359acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti            notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_NETWORK);
3369acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti            return;
3379acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti        }
3389acca09527eedfd5e9b2797eec4864fb46a699d7Lorenzo Colitti
3398bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        InetAddress srcAddress, dstAddress;
3408bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        try {
3418bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
3428bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
3438bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        } catch (IllegalArgumentException e) {
3448bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_IP_ADDRESS);
3458bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return;
3468bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
3478bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
3488bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        KeepalivePacketData packet;
3498bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        try {
3508bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            packet = KeepalivePacketData.nattKeepalivePacket(
3518bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                    srcAddress, srcPort, dstAddress, NATT_PORT);
3528bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        } catch (KeepalivePacketData.InvalidPacketException e) {
3538bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            notifyMessenger(messenger, NO_KEEPALIVE, e.error);
3548bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            return;
3558bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
3568bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds);
3578bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        Log.d(TAG, "Created keepalive: " + ki.toString());
3588bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        mConnectivityServiceHandler.obtainMessage(
3598bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                NetworkAgent.CMD_START_PACKET_KEEPALIVE, ki).sendToTarget();
3608bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
3618bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti
3628bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    public void dump(IndentingPrintWriter pw) {
3638bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        pw.println("Packet keepalives:");
3648bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        pw.increaseIndent();
3658bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        for (NetworkAgentInfo nai : mKeepalives.keySet()) {
3668bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            pw.println(nai.name());
3678bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            pw.increaseIndent();
3688bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            for (int slot : mKeepalives.get(nai).keySet()) {
3698bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                KeepaliveInfo ki = mKeepalives.get(nai).get(slot);
3708bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti                pw.println(slot + ": " + ki.toString());
3718bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            }
3728bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti            pw.decreaseIndent();
3738bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        }
3748bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti        pw.decreaseIndent();
3758bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti    }
3768bf977d562b8f7261cf964bdf045b22bdbd92b7dLorenzo Colitti}
377