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