Home | History | Annotate | Download | only in connectivity
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.connectivity;
     18 
     19 import static android.Manifest.permission.BIND_VPN_SERVICE;
     20 import static android.net.ConnectivityManager.NETID_UNSET;
     21 import static android.net.RouteInfo.RTN_THROW;
     22 import static android.net.RouteInfo.RTN_UNREACHABLE;
     23 
     24 import android.Manifest;
     25 import android.annotation.NonNull;
     26 import android.annotation.Nullable;
     27 import android.annotation.UserIdInt;
     28 import android.app.AppGlobals;
     29 import android.app.AppOpsManager;
     30 import android.app.PendingIntent;
     31 import android.content.BroadcastReceiver;
     32 import android.content.ComponentName;
     33 import android.content.ContentResolver;
     34 import android.content.Context;
     35 import android.content.Intent;
     36 import android.content.IntentFilter;
     37 import android.content.ServiceConnection;
     38 import android.content.pm.PackageManager;
     39 import android.content.pm.PackageManager.NameNotFoundException;
     40 import android.content.pm.ResolveInfo;
     41 import android.content.pm.UserInfo;
     42 import android.net.ConnectivityManager;
     43 import android.net.INetworkManagementEventObserver;
     44 import android.net.IpPrefix;
     45 import android.net.LinkAddress;
     46 import android.net.LinkProperties;
     47 import android.net.LocalSocket;
     48 import android.net.LocalSocketAddress;
     49 import android.net.Network;
     50 import android.net.NetworkAgent;
     51 import android.net.NetworkCapabilities;
     52 import android.net.NetworkInfo;
     53 import android.net.NetworkInfo.DetailedState;
     54 import android.net.NetworkMisc;
     55 import android.net.RouteInfo;
     56 import android.net.UidRange;
     57 import android.net.Uri;
     58 import android.os.Binder;
     59 import android.os.FileUtils;
     60 import android.os.IBinder;
     61 import android.os.INetworkManagementService;
     62 import android.os.Looper;
     63 import android.os.Parcel;
     64 import android.os.ParcelFileDescriptor;
     65 import android.os.PatternMatcher;
     66 import android.os.Process;
     67 import android.os.RemoteException;
     68 import android.os.SystemClock;
     69 import android.os.SystemService;
     70 import android.os.UserHandle;
     71 import android.os.UserManager;
     72 import android.provider.Settings;
     73 import android.security.Credentials;
     74 import android.security.KeyStore;
     75 import android.text.TextUtils;
     76 import android.util.ArraySet;
     77 import android.util.Log;
     78 
     79 import com.android.internal.annotations.GuardedBy;
     80 import com.android.internal.annotations.VisibleForTesting;
     81 import com.android.internal.net.LegacyVpnInfo;
     82 import com.android.internal.net.VpnConfig;
     83 import com.android.internal.net.VpnInfo;
     84 import com.android.internal.net.VpnProfile;
     85 import com.android.server.net.BaseNetworkObserver;
     86 
     87 import libcore.io.IoUtils;
     88 
     89 import java.io.File;
     90 import java.io.IOException;
     91 import java.io.InputStream;
     92 import java.io.OutputStream;
     93 import java.net.Inet4Address;
     94 import java.net.Inet6Address;
     95 import java.net.InetAddress;
     96 import java.nio.charset.StandardCharsets;
     97 import java.util.ArrayList;
     98 import java.util.Arrays;
     99 import java.util.Collection;
    100 import java.util.Collections;
    101 import java.util.List;
    102 import java.util.Set;
    103 import java.util.SortedSet;
    104 import java.util.TreeSet;
    105 import java.util.concurrent.atomic.AtomicInteger;
    106 
    107 /**
    108  * @hide
    109  */
    110 public class Vpn {
    111     private static final String NETWORKTYPE = "VPN";
    112     private static final String TAG = "Vpn";
    113     private static final boolean LOGD = true;
    114 
    115     // TODO: create separate trackers for each unique VPN to support
    116     // automated reconnection
    117 
    118     private Context mContext;
    119     private NetworkInfo mNetworkInfo;
    120     private String mPackage;
    121     private int mOwnerUID;
    122     private String mInterface;
    123     private Connection mConnection;
    124     private LegacyVpnRunner mLegacyVpnRunner;
    125     private PendingIntent mStatusIntent;
    126     private volatile boolean mEnableTeardown = true;
    127     private final INetworkManagementService mNetd;
    128     private VpnConfig mConfig;
    129     private NetworkAgent mNetworkAgent;
    130     private final Looper mLooper;
    131     private final NetworkCapabilities mNetworkCapabilities;
    132 
    133     /**
    134      * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
    135      * only applies to {@link VpnService} connections.
    136      */
    137     private boolean mAlwaysOn = false;
    138 
    139     /**
    140      * Whether to disable traffic outside of this VPN even when the VPN is not connected. System
    141      * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is
    142      * not set.
    143      */
    144     private boolean mLockdown = false;
    145 
    146     /**
    147      * List of UIDs that are set to use this VPN by default. Normally, every UID in the user is
    148      * added to this set but that can be changed by adding allowed or disallowed applications. It
    149      * is non-null iff the VPN is connected.
    150      *
    151      * Unless the VPN has set allowBypass=true, these UIDs are forced into the VPN.
    152      *
    153      * @see VpnService.Builder#addAllowedApplication(String)
    154      * @see VpnService.Builder#addDisallowedApplication(String)
    155      */
    156     @GuardedBy("this")
    157     private Set<UidRange> mVpnUsers = null;
    158 
    159     /**
    160      * List of UIDs for which networking should be blocked until VPN is ready, during brief periods
    161      * when VPN is not running. For example, during system startup or after a crash.
    162      * @see mLockdown
    163      */
    164     @GuardedBy("this")
    165     private Set<UidRange> mBlockedUsers = new ArraySet<>();
    166 
    167     // Handle of user initiating VPN.
    168     private final int mUserHandle;
    169 
    170     // Listen to package remove and change event in this user
    171     private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
    172         @Override
    173         public void onReceive(Context context, Intent intent) {
    174             final Uri data = intent.getData();
    175             final String packageName = data == null ? null : data.getSchemeSpecificPart();
    176             if (packageName == null) {
    177                 return;
    178             }
    179 
    180             synchronized (Vpn.this) {
    181                 // Avoid race that always-on package has been unset
    182                 if (!packageName.equals(getAlwaysOnPackage())) {
    183                     return;
    184                 }
    185 
    186                 final String action = intent.getAction();
    187                 Log.i(TAG, "Received broadcast " + action + " for always-on package " + packageName
    188                         + " in user " + mUserHandle);
    189 
    190                 switch(action) {
    191                     case Intent.ACTION_PACKAGE_REPLACED:
    192                         // Start vpn after app upgrade
    193                         startAlwaysOnVpn();
    194                         break;
    195                     case Intent.ACTION_PACKAGE_REMOVED:
    196                         final boolean isPackageRemoved = !intent.getBooleanExtra(
    197                                 Intent.EXTRA_REPLACING, false);
    198                         if (isPackageRemoved) {
    199                             setAndSaveAlwaysOnPackage(null, false);
    200                         }
    201                         break;
    202                 }
    203             }
    204         }
    205     };
    206 
    207     private boolean mIsPackageIntentReceiverRegistered = false;
    208 
    209     public Vpn(Looper looper, Context context, INetworkManagementService netService,
    210             int userHandle) {
    211         mContext = context;
    212         mNetd = netService;
    213         mUserHandle = userHandle;
    214         mLooper = looper;
    215 
    216         mPackage = VpnConfig.LEGACY_VPN;
    217         mOwnerUID = getAppUid(mPackage, mUserHandle);
    218 
    219         try {
    220             netService.registerObserver(mObserver);
    221         } catch (RemoteException e) {
    222             Log.wtf(TAG, "Problem registering observer", e);
    223         }
    224 
    225         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, "");
    226         // TODO: Copy metered attribute and bandwidths from physical transport, b/16207332
    227         mNetworkCapabilities = new NetworkCapabilities();
    228         mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
    229         mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
    230     }
    231 
    232     /**
    233      * Set if this object is responsible for watching for {@link NetworkInfo}
    234      * teardown. When {@code false}, teardown is handled externally by someone
    235      * else.
    236      */
    237     public void setEnableTeardown(boolean enableTeardown) {
    238         mEnableTeardown = enableTeardown;
    239     }
    240 
    241     /**
    242      * Update current state, dispaching event to listeners.
    243      */
    244     private void updateState(DetailedState detailedState, String reason) {
    245         if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason);
    246         mNetworkInfo.setDetailedState(detailedState, reason, null);
    247         if (mNetworkAgent != null) {
    248             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
    249         }
    250     }
    251 
    252     /**
    253      * Configures an always-on VPN connection through a specific application.
    254      * This connection is automatically granted and persisted after a reboot.
    255      *
    256      * <p>The designated package should exist and declare a {@link VpnService} in its
    257      *    manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
    258      *    otherwise the call will fail.
    259      *
    260      * @param packageName the package to designate as always-on VPN supplier.
    261      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
    262      * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
    263      */
    264     public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) {
    265         enforceControlPermissionOrInternalCaller();
    266         if (VpnConfig.LEGACY_VPN.equals(packageName)) {
    267             Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
    268             return false;
    269         }
    270 
    271         if (packageName != null) {
    272             // Pre-authorize new always-on VPN package.
    273             if (!setPackageAuthorization(packageName, true)) {
    274                 return false;
    275             }
    276             mAlwaysOn = true;
    277         } else {
    278             packageName = VpnConfig.LEGACY_VPN;
    279             mAlwaysOn = false;
    280         }
    281 
    282         mLockdown = (mAlwaysOn && lockdown);
    283         if (!isCurrentPreparedPackage(packageName)) {
    284             prepareInternal(packageName);
    285         }
    286         maybeRegisterPackageChangeReceiverLocked(packageName);
    287         setVpnForcedLocked(mLockdown);
    288         return true;
    289     }
    290 
    291     private static boolean isNullOrLegacyVpn(String packageName) {
    292         return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName);
    293     }
    294 
    295     private void unregisterPackageChangeReceiverLocked() {
    296         // register previous intent filter
    297         if (mIsPackageIntentReceiverRegistered) {
    298             mContext.unregisterReceiver(mPackageIntentReceiver);
    299             mIsPackageIntentReceiverRegistered = false;
    300         }
    301     }
    302 
    303     private void maybeRegisterPackageChangeReceiverLocked(String packageName) {
    304         // Unregister IntentFilter listening for previous always-on package change
    305         unregisterPackageChangeReceiverLocked();
    306 
    307         if (!isNullOrLegacyVpn(packageName)) {
    308             mIsPackageIntentReceiverRegistered = true;
    309 
    310             IntentFilter intentFilter = new IntentFilter();
    311             // Protected intent can only be sent by system. No permission required in register.
    312             intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
    313             intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    314             intentFilter.addDataScheme("package");
    315             intentFilter.addDataSchemeSpecificPart(packageName, PatternMatcher.PATTERN_LITERAL);
    316             mContext.registerReceiverAsUser(
    317                     mPackageIntentReceiver, UserHandle.of(mUserHandle), intentFilter, null, null);
    318         }
    319     }
    320 
    321     /**
    322      * @return the package name of the VPN controller responsible for always-on VPN,
    323      *         or {@code null} if none is set or always-on VPN is controlled through
    324      *         lockdown instead.
    325      * @hide
    326      */
    327     public synchronized String getAlwaysOnPackage() {
    328         enforceControlPermissionOrInternalCaller();
    329         return (mAlwaysOn ? mPackage : null);
    330     }
    331 
    332     /**
    333      * Save the always-on package and lockdown config into Settings.Secure
    334      */
    335     public synchronized void saveAlwaysOnPackage() {
    336         final long token = Binder.clearCallingIdentity();
    337         try {
    338             final ContentResolver cr = mContext.getContentResolver();
    339             Settings.Secure.putStringForUser(cr, Settings.Secure.ALWAYS_ON_VPN_APP,
    340                     getAlwaysOnPackage(), mUserHandle);
    341             Settings.Secure.putIntForUser(cr, Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
    342                     (mLockdown ? 1 : 0), mUserHandle);
    343         } finally {
    344             Binder.restoreCallingIdentity(token);
    345         }
    346     }
    347 
    348     /**
    349      * Set and save always-on package and lockdown config
    350      * @see Vpn#setAlwaysOnPackage(String, boolean)
    351      * @see Vpn#saveAlwaysOnPackage()
    352      *
    353      * @return result of Vpn#setAndSaveAlwaysOnPackage(String, boolean)
    354      */
    355     private synchronized boolean setAndSaveAlwaysOnPackage(String packageName, boolean lockdown) {
    356         if (setAlwaysOnPackage(packageName, lockdown)) {
    357             saveAlwaysOnPackage();
    358             return true;
    359         } else {
    360             return false;
    361         }
    362     }
    363 
    364     /**
    365      * @return {@code true} if the service was started, the service was already connected, or there
    366      *         was no always-on VPN to start. {@code false} otherwise.
    367      */
    368     public boolean startAlwaysOnVpn() {
    369         final String alwaysOnPackage;
    370         synchronized (this) {
    371             alwaysOnPackage = getAlwaysOnPackage();
    372             // Skip if there is no service to start.
    373             if (alwaysOnPackage == null) {
    374                 return true;
    375             }
    376             // Skip if the service is already established. This isn't bulletproof: it's not bound
    377             // until after establish(), so if it's mid-setup onStartCommand will be sent twice,
    378             // which may restart the connection.
    379             if (getNetworkInfo().isConnected()) {
    380                 return true;
    381             }
    382         }
    383 
    384         // Start the VPN service declared in the app's manifest.
    385         Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE);
    386         serviceIntent.setPackage(alwaysOnPackage);
    387         try {
    388             return mContext.startServiceAsUser(serviceIntent, UserHandle.of(mUserHandle)) != null;
    389         } catch (RuntimeException e) {
    390             Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e);
    391             return false;
    392         }
    393     }
    394 
    395     /**
    396      * Prepare for a VPN application. This method is designed to solve
    397      * race conditions. It first compares the current prepared package
    398      * with {@code oldPackage}. If they are the same, the prepared
    399      * package is revoked and replaced with {@code newPackage}. If
    400      * {@code oldPackage} is {@code null}, the comparison is omitted.
    401      * If {@code newPackage} is the same package or {@code null}, the
    402      * revocation is omitted. This method returns {@code true} if the
    403      * operation is succeeded.
    404      *
    405      * Legacy VPN is handled specially since it is not a real package.
    406      * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and
    407      * it can be revoked by itself.
    408      *
    409      * Note: when we added VPN pre-consent in http://ag/522961 the names oldPackage
    410      * and newPackage become misleading, because when an app is pre-consented, we
    411      * actually prepare oldPackage, not newPackage.
    412      *
    413      * Their meanings actually are:
    414      *
    415      * - oldPackage non-null, newPackage null: App calling VpnService#prepare().
    416      * - oldPackage null, newPackage non-null: ConfirmDialog calling prepareVpn().
    417      * - oldPackage null, newPackage=LEGACY_VPN: Used internally to disconnect
    418      *   and revoke any current app VPN and re-prepare legacy vpn.
    419      *
    420      * TODO: Rename the variables - or split this method into two - and end this confusion.
    421      * TODO: b/29032008 Migrate code from prepare(oldPackage=non-null, newPackage=LEGACY_VPN)
    422      * to prepare(oldPackage=null, newPackage=LEGACY_VPN)
    423      *
    424      * @param oldPackage The package name of the old VPN application
    425      * @param newPackage The package name of the new VPN application
    426      *
    427      * @return true if the operation is succeeded.
    428      */
    429     public synchronized boolean prepare(String oldPackage, String newPackage) {
    430         if (oldPackage != null) {
    431             // Stop an existing always-on VPN from being dethroned by other apps.
    432             if (mAlwaysOn && !isCurrentPreparedPackage(oldPackage)) {
    433                 return false;
    434             }
    435 
    436             // Package is not same or old package was reinstalled.
    437             if (!isCurrentPreparedPackage(oldPackage)) {
    438                 // The package doesn't match. We return false (to obtain user consent) unless the
    439                 // user has already consented to that VPN package.
    440                 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) {
    441                     prepareInternal(oldPackage);
    442                     return true;
    443                 }
    444                 return false;
    445             } else if (!oldPackage.equals(VpnConfig.LEGACY_VPN)
    446                     && !isVpnUserPreConsented(oldPackage)) {
    447                 // Currently prepared VPN is revoked, so unprepare it and return false.
    448                 prepareInternal(VpnConfig.LEGACY_VPN);
    449                 return false;
    450             }
    451         }
    452 
    453         // Return true if we do not need to revoke.
    454         if (newPackage == null || (!newPackage.equals(VpnConfig.LEGACY_VPN) &&
    455                 isCurrentPreparedPackage(newPackage))) {
    456             return true;
    457         }
    458 
    459         // Check that the caller is authorized.
    460         enforceControlPermission();
    461 
    462         // Stop an existing always-on VPN from being dethroned by other apps.
    463         if (mAlwaysOn && !isCurrentPreparedPackage(newPackage)) {
    464             return false;
    465         }
    466 
    467         prepareInternal(newPackage);
    468         return true;
    469     }
    470 
    471     private boolean isCurrentPreparedPackage(String packageName) {
    472         // We can't just check that packageName matches mPackage, because if the app was uninstalled
    473         // and reinstalled it will no longer be prepared. Instead check the UID.
    474         return getAppUid(packageName, mUserHandle) == mOwnerUID;
    475     }
    476 
    477     /** Prepare the VPN for the given package. Does not perform permission checks. */
    478     private void prepareInternal(String newPackage) {
    479         long token = Binder.clearCallingIdentity();
    480         try {
    481             // Reset the interface.
    482             if (mInterface != null) {
    483                 mStatusIntent = null;
    484                 agentDisconnect();
    485                 jniReset(mInterface);
    486                 mInterface = null;
    487                 mVpnUsers = null;
    488             }
    489 
    490             // Revoke the connection or stop LegacyVpnRunner.
    491             if (mConnection != null) {
    492                 try {
    493                     mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION,
    494                             Parcel.obtain(), null, IBinder.FLAG_ONEWAY);
    495                 } catch (Exception e) {
    496                     // ignore
    497                 }
    498                 mContext.unbindService(mConnection);
    499                 mConnection = null;
    500             } else if (mLegacyVpnRunner != null) {
    501                 mLegacyVpnRunner.exit();
    502                 mLegacyVpnRunner = null;
    503             }
    504 
    505             try {
    506                 mNetd.denyProtect(mOwnerUID);
    507             } catch (Exception e) {
    508                 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e);
    509             }
    510 
    511             Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
    512             mPackage = newPackage;
    513             mOwnerUID = getAppUid(newPackage, mUserHandle);
    514             try {
    515                 mNetd.allowProtect(mOwnerUID);
    516             } catch (Exception e) {
    517                 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e);
    518             }
    519             mConfig = null;
    520 
    521             updateState(DetailedState.IDLE, "prepare");
    522         } finally {
    523             Binder.restoreCallingIdentity(token);
    524         }
    525     }
    526 
    527     /**
    528      * Set whether a package has the ability to launch VPNs without user intervention.
    529      */
    530     public boolean setPackageAuthorization(String packageName, boolean authorized) {
    531         // Check if the caller is authorized.
    532         enforceControlPermissionOrInternalCaller();
    533 
    534         int uid = getAppUid(packageName, mUserHandle);
    535         if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) {
    536             // Authorization for nonexistent packages (or fake ones) can't be updated.
    537             return false;
    538         }
    539 
    540         long token = Binder.clearCallingIdentity();
    541         try {
    542             AppOpsManager appOps =
    543                     (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    544             appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, uid, packageName,
    545                     authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
    546             return true;
    547         } catch (Exception e) {
    548             Log.wtf(TAG, "Failed to set app ops for package " + packageName + ", uid " + uid, e);
    549         } finally {
    550             Binder.restoreCallingIdentity(token);
    551         }
    552         return false;
    553     }
    554 
    555     private boolean isVpnUserPreConsented(String packageName) {
    556         AppOpsManager appOps =
    557                 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
    558 
    559         // Verify that the caller matches the given package and has permission to activate VPNs.
    560         return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(),
    561                 packageName) == AppOpsManager.MODE_ALLOWED;
    562     }
    563 
    564     private int getAppUid(String app, int userHandle) {
    565         if (VpnConfig.LEGACY_VPN.equals(app)) {
    566             return Process.myUid();
    567         }
    568         PackageManager pm = mContext.getPackageManager();
    569         int result;
    570         try {
    571             result = pm.getPackageUidAsUser(app, userHandle);
    572         } catch (NameNotFoundException e) {
    573             result = -1;
    574         }
    575         return result;
    576     }
    577 
    578     public NetworkInfo getNetworkInfo() {
    579         return mNetworkInfo;
    580     }
    581 
    582     public int getNetId() {
    583         return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET;
    584     }
    585 
    586     private LinkProperties makeLinkProperties() {
    587         boolean allowIPv4 = mConfig.allowIPv4;
    588         boolean allowIPv6 = mConfig.allowIPv6;
    589 
    590         LinkProperties lp = new LinkProperties();
    591 
    592         lp.setInterfaceName(mInterface);
    593 
    594         if (mConfig.addresses != null) {
    595             for (LinkAddress address : mConfig.addresses) {
    596                 lp.addLinkAddress(address);
    597                 allowIPv4 |= address.getAddress() instanceof Inet4Address;
    598                 allowIPv6 |= address.getAddress() instanceof Inet6Address;
    599             }
    600         }
    601 
    602         if (mConfig.routes != null) {
    603             for (RouteInfo route : mConfig.routes) {
    604                 lp.addRoute(route);
    605                 InetAddress address = route.getDestination().getAddress();
    606                 allowIPv4 |= address instanceof Inet4Address;
    607                 allowIPv6 |= address instanceof Inet6Address;
    608             }
    609         }
    610 
    611         if (mConfig.dnsServers != null) {
    612             for (String dnsServer : mConfig.dnsServers) {
    613                 InetAddress address = InetAddress.parseNumericAddress(dnsServer);
    614                 lp.addDnsServer(address);
    615                 allowIPv4 |= address instanceof Inet4Address;
    616                 allowIPv6 |= address instanceof Inet6Address;
    617             }
    618         }
    619 
    620         if (!allowIPv4) {
    621             lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
    622         }
    623         if (!allowIPv6) {
    624             lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
    625         }
    626 
    627         // Concatenate search domains into a string.
    628         StringBuilder buffer = new StringBuilder();
    629         if (mConfig.searchDomains != null) {
    630             for (String domain : mConfig.searchDomains) {
    631                 buffer.append(domain).append(' ');
    632             }
    633         }
    634         lp.setDomains(buffer.toString().trim());
    635 
    636         // TODO: Stop setting the MTU in jniCreate and set it here.
    637 
    638         return lp;
    639     }
    640 
    641     private void agentConnect() {
    642         LinkProperties lp = makeLinkProperties();
    643 
    644         if (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()) {
    645             mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    646         } else {
    647             mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    648         }
    649 
    650         mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null);
    651 
    652         NetworkMisc networkMisc = new NetworkMisc();
    653         networkMisc.allowBypass = mConfig.allowBypass && !mLockdown;
    654 
    655         long token = Binder.clearCallingIdentity();
    656         try {
    657             mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE,
    658                     mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) {
    659                             @Override
    660                             public void unwanted() {
    661                                 // We are user controlled, not driven by NetworkRequest.
    662                             }
    663                         };
    664         } finally {
    665             Binder.restoreCallingIdentity(token);
    666         }
    667 
    668         mVpnUsers = createUserAndRestrictedProfilesRanges(mUserHandle,
    669                 mConfig.allowedApplications, mConfig.disallowedApplications);
    670         mNetworkAgent.addUidRanges(mVpnUsers.toArray(new UidRange[mVpnUsers.size()]));
    671 
    672         mNetworkInfo.setIsAvailable(true);
    673         updateState(DetailedState.CONNECTED, "agentConnect");
    674     }
    675 
    676     private boolean canHaveRestrictedProfile(int userId) {
    677         long token = Binder.clearCallingIdentity();
    678         try {
    679             return UserManager.get(mContext).canHaveRestrictedProfile(userId);
    680         } finally {
    681             Binder.restoreCallingIdentity(token);
    682         }
    683     }
    684 
    685     private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) {
    686         networkInfo.setIsAvailable(false);
    687         networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
    688         if (networkAgent != null) {
    689             networkAgent.sendNetworkInfo(networkInfo);
    690         }
    691     }
    692 
    693     private void agentDisconnect(NetworkAgent networkAgent) {
    694         NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo);
    695         agentDisconnect(networkInfo, networkAgent);
    696     }
    697 
    698     private void agentDisconnect() {
    699         if (mNetworkInfo.isConnected()) {
    700             agentDisconnect(mNetworkInfo, mNetworkAgent);
    701             mNetworkAgent = null;
    702         }
    703     }
    704 
    705     /**
    706      * Establish a VPN network and return the file descriptor of the VPN
    707      * interface. This methods returns {@code null} if the application is
    708      * revoked or not prepared.
    709      *
    710      * @param config The parameters to configure the network.
    711      * @return The file descriptor of the VPN interface.
    712      */
    713     public synchronized ParcelFileDescriptor establish(VpnConfig config) {
    714         // Check if the caller is already prepared.
    715         UserManager mgr = UserManager.get(mContext);
    716         if (Binder.getCallingUid() != mOwnerUID) {
    717             return null;
    718         }
    719         // Check to ensure consent hasn't been revoked since we were prepared.
    720         if (!isVpnUserPreConsented(mPackage)) {
    721             return null;
    722         }
    723         // Check if the service is properly declared.
    724         Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
    725         intent.setClassName(mPackage, config.user);
    726         long token = Binder.clearCallingIdentity();
    727         try {
    728             // Restricted users are not allowed to create VPNs, they are tied to Owner
    729             UserInfo user = mgr.getUserInfo(mUserHandle);
    730             if (user.isRestricted()) {
    731                 throw new SecurityException("Restricted users cannot establish VPNs");
    732             }
    733 
    734             ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent,
    735                                                                         null, 0, mUserHandle);
    736             if (info == null) {
    737                 throw new SecurityException("Cannot find " + config.user);
    738             }
    739             if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
    740                 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
    741             }
    742         } catch (RemoteException e) {
    743                 throw new SecurityException("Cannot find " + config.user);
    744         } finally {
    745             Binder.restoreCallingIdentity(token);
    746         }
    747 
    748         // Save the old config in case we need to go back.
    749         VpnConfig oldConfig = mConfig;
    750         String oldInterface = mInterface;
    751         Connection oldConnection = mConnection;
    752         NetworkAgent oldNetworkAgent = mNetworkAgent;
    753         mNetworkAgent = null;
    754         Set<UidRange> oldUsers = mVpnUsers;
    755 
    756         // Configure the interface. Abort if any of these steps fails.
    757         ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
    758         try {
    759             updateState(DetailedState.CONNECTING, "establish");
    760             String interfaze = jniGetName(tun.getFd());
    761 
    762             // TEMP use the old jni calls until there is support for netd address setting
    763             StringBuilder builder = new StringBuilder();
    764             for (LinkAddress address : config.addresses) {
    765                 builder.append(" " + address);
    766             }
    767             if (jniSetAddresses(interfaze, builder.toString()) < 1) {
    768                 throw new IllegalArgumentException("At least one address must be specified");
    769             }
    770             Connection connection = new Connection();
    771             if (!mContext.bindServiceAsUser(intent, connection,
    772                     Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
    773                     new UserHandle(mUserHandle))) {
    774                 throw new IllegalStateException("Cannot bind " + config.user);
    775             }
    776 
    777             mConnection = connection;
    778             mInterface = interfaze;
    779 
    780             // Fill more values.
    781             config.user = mPackage;
    782             config.interfaze = mInterface;
    783             config.startTime = SystemClock.elapsedRealtime();
    784             mConfig = config;
    785 
    786             // Set up forwarding and DNS rules.
    787             agentConnect();
    788 
    789             if (oldConnection != null) {
    790                 mContext.unbindService(oldConnection);
    791             }
    792             // Remove the old tun's user forwarding rules
    793             // The new tun's user rules have already been added so they will take over
    794             // as rules are deleted. This prevents data leakage as the rules are moved over.
    795             agentDisconnect(oldNetworkAgent);
    796             if (oldInterface != null && !oldInterface.equals(interfaze)) {
    797                 jniReset(oldInterface);
    798             }
    799 
    800             try {
    801                 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking);
    802             } catch (IOException e) {
    803                 throw new IllegalStateException(
    804                         "Cannot set tunnel's fd as blocking=" + config.blocking, e);
    805             }
    806         } catch (RuntimeException e) {
    807             IoUtils.closeQuietly(tun);
    808             agentDisconnect();
    809             // restore old state
    810             mConfig = oldConfig;
    811             mConnection = oldConnection;
    812             mVpnUsers = oldUsers;
    813             mNetworkAgent = oldNetworkAgent;
    814             mInterface = oldInterface;
    815             throw e;
    816         }
    817         Log.i(TAG, "Established by " + config.user + " on " + mInterface);
    818         return tun;
    819     }
    820 
    821     private boolean isRunningLocked() {
    822         return mNetworkAgent != null && mInterface != null;
    823     }
    824 
    825     // Returns true if the VPN has been established and the calling UID is its owner. Used to check
    826     // that a call to mutate VPN state is admissible.
    827     private boolean isCallerEstablishedOwnerLocked() {
    828         return isRunningLocked() && Binder.getCallingUid() == mOwnerUID;
    829     }
    830 
    831     // Note: Return type guarantees results are deduped and sorted, which callers require.
    832     private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) {
    833         SortedSet<Integer> uids = new TreeSet<Integer>();
    834         for (String app : packageNames) {
    835             int uid = getAppUid(app, userHandle);
    836             if (uid != -1) uids.add(uid);
    837         }
    838         return uids;
    839     }
    840 
    841     /**
    842      * Creates a {@link Set} of non-intersecting {@link UidRange} objects including all UIDs
    843      * associated with one user, and any restricted profiles attached to that user.
    844      *
    845      * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
    846      * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
    847      * in each user and profile will be included.
    848      *
    849      * @param userHandle The userId to create UID ranges for along with any of its restricted
    850      *                   profiles.
    851      * @param allowedApplications (optional) whitelist of applications to include.
    852      * @param disallowedApplications (optional) blacklist of applications to exclude.
    853      */
    854     @VisibleForTesting
    855     Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle,
    856             @Nullable List<String> allowedApplications,
    857             @Nullable List<String> disallowedApplications) {
    858         final Set<UidRange> ranges = new ArraySet<>();
    859 
    860         // Assign the top-level user to the set of ranges
    861         addUserToRanges(ranges, userHandle, allowedApplications, disallowedApplications);
    862 
    863         // If the user can have restricted profiles, assign all its restricted profiles too
    864         if (canHaveRestrictedProfile(userHandle)) {
    865             final long token = Binder.clearCallingIdentity();
    866             List<UserInfo> users;
    867             try {
    868                 users = UserManager.get(mContext).getUsers(true);
    869             } finally {
    870                 Binder.restoreCallingIdentity(token);
    871             }
    872             for (UserInfo user : users) {
    873                 if (user.isRestricted() && (user.restrictedProfileParentId == userHandle)) {
    874                     addUserToRanges(ranges, user.id, allowedApplications, disallowedApplications);
    875                 }
    876             }
    877         }
    878         return ranges;
    879     }
    880 
    881     /**
    882      * Updates a {@link Set} of non-intersecting {@link UidRange} objects to include all UIDs
    883      * associated with one user.
    884      *
    885      * <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
    886      * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
    887      * in the user will be included.
    888      *
    889      * @param ranges {@link Set} of {@link UidRange}s to which to add.
    890      * @param userHandle The userId to add to {@param ranges}.
    891      * @param allowedApplications (optional) whitelist of applications to include.
    892      * @param disallowedApplications (optional) blacklist of applications to exclude.
    893      */
    894     @VisibleForTesting
    895     void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle,
    896             @Nullable List<String> allowedApplications,
    897             @Nullable List<String> disallowedApplications) {
    898         if (allowedApplications != null) {
    899             // Add ranges covering all UIDs for allowedApplications.
    900             int start = -1, stop = -1;
    901             for (int uid : getAppsUids(allowedApplications, userHandle)) {
    902                 if (start == -1) {
    903                     start = uid;
    904                 } else if (uid != stop + 1) {
    905                     ranges.add(new UidRange(start, stop));
    906                     start = uid;
    907                 }
    908                 stop = uid;
    909             }
    910             if (start != -1) ranges.add(new UidRange(start, stop));
    911         } else if (disallowedApplications != null) {
    912             // Add all ranges for user skipping UIDs for disallowedApplications.
    913             final UidRange userRange = UidRange.createForUser(userHandle);
    914             int start = userRange.start;
    915             for (int uid : getAppsUids(disallowedApplications, userHandle)) {
    916                 if (uid == start) {
    917                     start++;
    918                 } else {
    919                     ranges.add(new UidRange(start, uid - 1));
    920                     start = uid + 1;
    921                 }
    922             }
    923             if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop));
    924         } else {
    925             // Add all UIDs for the user.
    926             ranges.add(UidRange.createForUser(userHandle));
    927         }
    928     }
    929 
    930     // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that
    931     // apply to userHandle.
    932     private List<UidRange> uidRangesForUser(int userHandle) {
    933         final UidRange userRange = UidRange.createForUser(userHandle);
    934         final List<UidRange> ranges = new ArrayList<UidRange>();
    935         for (UidRange range : mVpnUsers) {
    936             if (userRange.containsRange(range)) {
    937                 ranges.add(range);
    938             }
    939         }
    940         return ranges;
    941     }
    942 
    943     private void removeVpnUserLocked(int userHandle) {
    944         if (mVpnUsers == null) {
    945             throw new IllegalStateException("VPN is not active");
    946         }
    947         final List<UidRange> ranges = uidRangesForUser(userHandle);
    948         if (mNetworkAgent != null) {
    949             mNetworkAgent.removeUidRanges(ranges.toArray(new UidRange[ranges.size()]));
    950         }
    951         mVpnUsers.removeAll(ranges);
    952     }
    953 
    954     public void onUserAdded(int userHandle) {
    955         // If the user is restricted tie them to the parent user's VPN
    956         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
    957         if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
    958             synchronized(Vpn.this) {
    959                 if (mVpnUsers != null) {
    960                     try {
    961                         addUserToRanges(mVpnUsers, userHandle, mConfig.allowedApplications,
    962                                 mConfig.disallowedApplications);
    963                         if (mNetworkAgent != null) {
    964                             final List<UidRange> ranges = uidRangesForUser(userHandle);
    965                             mNetworkAgent.addUidRanges(ranges.toArray(new UidRange[ranges.size()]));
    966                         }
    967                     } catch (Exception e) {
    968                         Log.wtf(TAG, "Failed to add restricted user to owner", e);
    969                     }
    970                 }
    971                 if (mAlwaysOn) {
    972                     setVpnForcedLocked(mLockdown);
    973                 }
    974             }
    975         }
    976     }
    977 
    978     public void onUserRemoved(int userHandle) {
    979         // clean up if restricted
    980         UserInfo user = UserManager.get(mContext).getUserInfo(userHandle);
    981         if (user.isRestricted() && user.restrictedProfileParentId == mUserHandle) {
    982             synchronized(Vpn.this) {
    983                 if (mVpnUsers != null) {
    984                     try {
    985                         removeVpnUserLocked(userHandle);
    986                     } catch (Exception e) {
    987                         Log.wtf(TAG, "Failed to remove restricted user to owner", e);
    988                     }
    989                 }
    990                 if (mAlwaysOn) {
    991                     setVpnForcedLocked(mLockdown);
    992                 }
    993             }
    994         }
    995     }
    996 
    997     /**
    998      * Called when the user associated with this VPN has just been stopped.
    999      */
   1000     public synchronized void onUserStopped() {
   1001         // Switch off networking lockdown (if it was enabled)
   1002         setVpnForcedLocked(false);
   1003         mAlwaysOn = false;
   1004 
   1005         unregisterPackageChangeReceiverLocked();
   1006         // Quit any active connections
   1007         agentDisconnect();
   1008     }
   1009 
   1010     /**
   1011      * Restrict network access from all UIDs affected by this {@link Vpn}, apart from the VPN
   1012      * service app itself, to only sockets that have had {@code protect()} called on them. All
   1013      * non-VPN traffic is blocked via a {@code PROHIBIT} response from the kernel.
   1014      *
   1015      * The exception for the VPN UID isn't technically necessary -- setup should use protected
   1016      * sockets -- but in practice it saves apps that don't protect their sockets from breaking.
   1017      *
   1018      * Calling multiple times with {@param enforce} = {@code true} will recreate the set of UIDs to
   1019      * block every time, and if anything has changed update using {@link #setAllowOnlyVpnForUids}.
   1020      *
   1021      * @param enforce {@code true} to require that all traffic under the jurisdiction of this
   1022      *                {@link Vpn} goes through a VPN connection or is blocked until one is
   1023      *                available, {@code false} to lift the requirement.
   1024      *
   1025      * @see #mBlockedUsers
   1026      */
   1027     @GuardedBy("this")
   1028     private void setVpnForcedLocked(boolean enforce) {
   1029         final Set<UidRange> removedRanges = new ArraySet<>(mBlockedUsers);
   1030         if (enforce) {
   1031             final Set<UidRange> addedRanges = createUserAndRestrictedProfilesRanges(mUserHandle,
   1032                     /* allowedApplications */ null,
   1033                     /* disallowedApplications */ Collections.singletonList(mPackage));
   1034 
   1035             removedRanges.removeAll(addedRanges);
   1036             addedRanges.removeAll(mBlockedUsers);
   1037 
   1038             setAllowOnlyVpnForUids(false, removedRanges);
   1039             setAllowOnlyVpnForUids(true, addedRanges);
   1040         } else {
   1041             setAllowOnlyVpnForUids(false, removedRanges);
   1042         }
   1043     }
   1044 
   1045     /**
   1046      * Either add or remove a list of {@link UidRange}s to the list of UIDs that are only allowed
   1047      * to make connections through sockets that have had {@code protect()} called on them.
   1048      *
   1049      * @param enforce {@code true} to add to the blacklist, {@code false} to remove.
   1050      * @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is
   1051      *               {@code true}) or to remove.
   1052      * @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise,
   1053      *         including added ranges that already existed or removed ones that didn't.
   1054      */
   1055     @GuardedBy("this")
   1056     private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) {
   1057         if (ranges.size() == 0) {
   1058             return true;
   1059         }
   1060         final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]);
   1061         try {
   1062             mNetd.setAllowOnlyVpnForUids(enforce, rangesArray);
   1063         } catch (RemoteException | RuntimeException e) {
   1064             Log.e(TAG, "Updating blocked=" + enforce
   1065                     + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e);
   1066             return false;
   1067         }
   1068         if (enforce) {
   1069             mBlockedUsers.addAll(ranges);
   1070         } else {
   1071             mBlockedUsers.removeAll(ranges);
   1072         }
   1073         return true;
   1074     }
   1075 
   1076     /**
   1077      * Return the configuration of the currently running VPN.
   1078      */
   1079     public VpnConfig getVpnConfig() {
   1080         enforceControlPermission();
   1081         return mConfig;
   1082     }
   1083 
   1084     @Deprecated
   1085     public synchronized void interfaceStatusChanged(String iface, boolean up) {
   1086         try {
   1087             mObserver.interfaceStatusChanged(iface, up);
   1088         } catch (RemoteException e) {
   1089             // ignored; target is local
   1090         }
   1091     }
   1092 
   1093     private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() {
   1094         @Override
   1095         public void interfaceStatusChanged(String interfaze, boolean up) {
   1096             synchronized (Vpn.this) {
   1097                 if (!up && mLegacyVpnRunner != null) {
   1098                     mLegacyVpnRunner.check(interfaze);
   1099                 }
   1100             }
   1101         }
   1102 
   1103         @Override
   1104         public void interfaceRemoved(String interfaze) {
   1105             synchronized (Vpn.this) {
   1106                 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) {
   1107                     mStatusIntent = null;
   1108                     mVpnUsers = null;
   1109                     mConfig = null;
   1110                     mInterface = null;
   1111                     if (mConnection != null) {
   1112                         mContext.unbindService(mConnection);
   1113                         mConnection = null;
   1114                         agentDisconnect();
   1115                     } else if (mLegacyVpnRunner != null) {
   1116                         mLegacyVpnRunner.exit();
   1117                         mLegacyVpnRunner = null;
   1118                     }
   1119                 }
   1120             }
   1121         }
   1122     };
   1123 
   1124     private void enforceControlPermission() {
   1125         mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller");
   1126     }
   1127 
   1128     private void enforceControlPermissionOrInternalCaller() {
   1129         // Require caller to be either an application with CONTROL_VPN permission or a process
   1130         // in the system server.
   1131         mContext.enforceCallingOrSelfPermission(Manifest.permission.CONTROL_VPN,
   1132                 "Unauthorized Caller");
   1133     }
   1134 
   1135     private class Connection implements ServiceConnection {
   1136         private IBinder mService;
   1137 
   1138         @Override
   1139         public void onServiceConnected(ComponentName name, IBinder service) {
   1140             mService = service;
   1141         }
   1142 
   1143         @Override
   1144         public void onServiceDisconnected(ComponentName name) {
   1145             mService = null;
   1146         }
   1147     }
   1148 
   1149     private void prepareStatusIntent() {
   1150         final long token = Binder.clearCallingIdentity();
   1151         try {
   1152             mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
   1153         } finally {
   1154             Binder.restoreCallingIdentity(token);
   1155         }
   1156     }
   1157 
   1158     public synchronized boolean addAddress(String address, int prefixLength) {
   1159         if (!isCallerEstablishedOwnerLocked()) {
   1160             return false;
   1161         }
   1162         boolean success = jniAddAddress(mInterface, address, prefixLength);
   1163         mNetworkAgent.sendLinkProperties(makeLinkProperties());
   1164         return success;
   1165     }
   1166 
   1167     public synchronized boolean removeAddress(String address, int prefixLength) {
   1168         if (!isCallerEstablishedOwnerLocked()) {
   1169             return false;
   1170         }
   1171         boolean success = jniDelAddress(mInterface, address, prefixLength);
   1172         mNetworkAgent.sendLinkProperties(makeLinkProperties());
   1173         return success;
   1174     }
   1175 
   1176     public synchronized boolean setUnderlyingNetworks(Network[] networks) {
   1177         if (!isCallerEstablishedOwnerLocked()) {
   1178             return false;
   1179         }
   1180         if (networks == null) {
   1181             mConfig.underlyingNetworks = null;
   1182         } else {
   1183             mConfig.underlyingNetworks = new Network[networks.length];
   1184             for (int i = 0; i < networks.length; ++i) {
   1185                 if (networks[i] == null) {
   1186                     mConfig.underlyingNetworks[i] = null;
   1187                 } else {
   1188                     mConfig.underlyingNetworks[i] = new Network(networks[i].netId);
   1189                 }
   1190             }
   1191         }
   1192         return true;
   1193     }
   1194 
   1195     public synchronized Network[] getUnderlyingNetworks() {
   1196         if (!isRunningLocked()) {
   1197             return null;
   1198         }
   1199         return mConfig.underlyingNetworks;
   1200     }
   1201 
   1202     /**
   1203      * This method should only be called by ConnectivityService. Because it doesn't
   1204      * have enough data to fill VpnInfo.primaryUnderlyingIface field.
   1205      */
   1206     public synchronized VpnInfo getVpnInfo() {
   1207         if (!isRunningLocked()) {
   1208             return null;
   1209         }
   1210 
   1211         VpnInfo info = new VpnInfo();
   1212         info.ownerUid = mOwnerUID;
   1213         info.vpnIface = mInterface;
   1214         return info;
   1215     }
   1216 
   1217     public synchronized boolean appliesToUid(int uid) {
   1218         if (!isRunningLocked()) {
   1219             return false;
   1220         }
   1221         for (UidRange uidRange : mVpnUsers) {
   1222             if (uidRange.contains(uid)) {
   1223                 return true;
   1224             }
   1225         }
   1226         return false;
   1227     }
   1228 
   1229     /**
   1230      * @return {@code true} if {@param uid} is blocked by an always-on VPN.
   1231      *         A UID is blocked if it's included in one of the mBlockedUsers ranges and the VPN is
   1232      *         not connected, or if the VPN is connected but does not apply to the UID.
   1233      *
   1234      * @see #mBlockedUsers
   1235      */
   1236     public synchronized boolean isBlockingUid(int uid) {
   1237         if (!mLockdown) {
   1238             return false;
   1239         }
   1240 
   1241         if (mNetworkInfo.isConnected()) {
   1242             return !appliesToUid(uid);
   1243         } else {
   1244             for (UidRange uidRange : mBlockedUsers) {
   1245                 if (uidRange.contains(uid)) {
   1246                     return true;
   1247                 }
   1248             }
   1249             return false;
   1250         }
   1251     }
   1252 
   1253     private native int jniCreate(int mtu);
   1254     private native String jniGetName(int tun);
   1255     private native int jniSetAddresses(String interfaze, String addresses);
   1256     private native void jniReset(String interfaze);
   1257     private native int jniCheck(String interfaze);
   1258     private native boolean jniAddAddress(String interfaze, String address, int prefixLen);
   1259     private native boolean jniDelAddress(String interfaze, String address, int prefixLen);
   1260 
   1261     private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
   1262         for (RouteInfo route : prop.getAllRoutes()) {
   1263             // Currently legacy VPN only works on IPv4.
   1264             if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
   1265                 return route;
   1266             }
   1267         }
   1268 
   1269         throw new IllegalStateException("Unable to find IPv4 default gateway");
   1270     }
   1271 
   1272     /**
   1273      * Start legacy VPN, controlling native daemons as needed. Creates a
   1274      * secondary thread to perform connection work, returning quickly.
   1275      *
   1276      * Should only be called to respond to Binder requests as this enforces caller permission. Use
   1277      * {@link #startLegacyVpnPrivileged(VpnProfile, KeyStore, LinkProperties)} to skip the
   1278      * permission check only when the caller is trusted (or the call is initiated by the system).
   1279      */
   1280     public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
   1281         enforceControlPermission();
   1282         long token = Binder.clearCallingIdentity();
   1283         try {
   1284             startLegacyVpnPrivileged(profile, keyStore, egress);
   1285         } finally {
   1286             Binder.restoreCallingIdentity(token);
   1287         }
   1288     }
   1289 
   1290     /**
   1291      * Like {@link #startLegacyVpn(VpnProfile, KeyStore, LinkProperties)}, but does not check
   1292      * permissions under the assumption that the caller is the system.
   1293      *
   1294      * Callers are responsible for checking permissions if needed.
   1295      */
   1296     public void startLegacyVpnPrivileged(VpnProfile profile, KeyStore keyStore,
   1297             LinkProperties egress) {
   1298         UserManager mgr = UserManager.get(mContext);
   1299         UserInfo user = mgr.getUserInfo(mUserHandle);
   1300         if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN,
   1301                     new UserHandle(mUserHandle))) {
   1302             throw new SecurityException("Restricted users cannot establish VPNs");
   1303         }
   1304 
   1305         final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress);
   1306         final String gateway = ipv4DefaultRoute.getGateway().getHostAddress();
   1307         final String iface = ipv4DefaultRoute.getInterface();
   1308 
   1309         // Load certificates.
   1310         String privateKey = "";
   1311         String userCert = "";
   1312         String caCert = "";
   1313         String serverCert = "";
   1314         if (!profile.ipsecUserCert.isEmpty()) {
   1315             privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert;
   1316             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert);
   1317             userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
   1318         }
   1319         if (!profile.ipsecCaCert.isEmpty()) {
   1320             byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
   1321             caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
   1322         }
   1323         if (!profile.ipsecServerCert.isEmpty()) {
   1324             byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
   1325             serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8);
   1326         }
   1327         if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
   1328             throw new IllegalStateException("Cannot load credentials");
   1329         }
   1330 
   1331         // Prepare arguments for racoon.
   1332         String[] racoon = null;
   1333         switch (profile.type) {
   1334             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
   1335                 racoon = new String[] {
   1336                     iface, profile.server, "udppsk", profile.ipsecIdentifier,
   1337                     profile.ipsecSecret, "1701",
   1338                 };
   1339                 break;
   1340             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
   1341                 racoon = new String[] {
   1342                     iface, profile.server, "udprsa", privateKey, userCert,
   1343                     caCert, serverCert, "1701",
   1344                 };
   1345                 break;
   1346             case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
   1347                 racoon = new String[] {
   1348                     iface, profile.server, "xauthpsk", profile.ipsecIdentifier,
   1349                     profile.ipsecSecret, profile.username, profile.password, "", gateway,
   1350                 };
   1351                 break;
   1352             case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
   1353                 racoon = new String[] {
   1354                     iface, profile.server, "xauthrsa", privateKey, userCert,
   1355                     caCert, serverCert, profile.username, profile.password, "", gateway,
   1356                 };
   1357                 break;
   1358             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
   1359                 racoon = new String[] {
   1360                     iface, profile.server, "hybridrsa",
   1361                     caCert, serverCert, profile.username, profile.password, "", gateway,
   1362                 };
   1363                 break;
   1364         }
   1365 
   1366         // Prepare arguments for mtpd.
   1367         String[] mtpd = null;
   1368         switch (profile.type) {
   1369             case VpnProfile.TYPE_PPTP:
   1370                 mtpd = new String[] {
   1371                     iface, "pptp", profile.server, "1723",
   1372                     "name", profile.username, "password", profile.password,
   1373                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
   1374                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
   1375                     (profile.mppe ? "+mppe" : "nomppe"),
   1376                 };
   1377                 break;
   1378             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
   1379             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
   1380                 mtpd = new String[] {
   1381                     iface, "l2tp", profile.server, "1701", profile.l2tpSecret,
   1382                     "name", profile.username, "password", profile.password,
   1383                     "linkname", "vpn", "refuse-eap", "nodefaultroute",
   1384                     "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400",
   1385                 };
   1386                 break;
   1387         }
   1388 
   1389         VpnConfig config = new VpnConfig();
   1390         config.legacy = true;
   1391         config.user = profile.key;
   1392         config.interfaze = iface;
   1393         config.session = profile.name;
   1394 
   1395         config.addLegacyRoutes(profile.routes);
   1396         if (!profile.dnsServers.isEmpty()) {
   1397             config.dnsServers = Arrays.asList(profile.dnsServers.split(" +"));
   1398         }
   1399         if (!profile.searchDomains.isEmpty()) {
   1400             config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
   1401         }
   1402         startLegacyVpn(config, racoon, mtpd);
   1403     }
   1404 
   1405     private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
   1406         stopLegacyVpnPrivileged();
   1407 
   1408         // Prepare for the new request.
   1409         prepareInternal(VpnConfig.LEGACY_VPN);
   1410         updateState(DetailedState.CONNECTING, "startLegacyVpn");
   1411 
   1412         // Start a new LegacyVpnRunner and we are done!
   1413         mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd);
   1414         mLegacyVpnRunner.start();
   1415     }
   1416 
   1417     /** Stop legacy VPN. Permissions must be checked by callers. */
   1418     public synchronized void stopLegacyVpnPrivileged() {
   1419         if (mLegacyVpnRunner != null) {
   1420             mLegacyVpnRunner.exit();
   1421             mLegacyVpnRunner = null;
   1422 
   1423             synchronized (LegacyVpnRunner.TAG) {
   1424                 // wait for old thread to completely finish before spinning up
   1425                 // new instance, otherwise state updates can be out of order.
   1426             }
   1427         }
   1428     }
   1429 
   1430     /**
   1431      * Return the information of the current ongoing legacy VPN.
   1432      */
   1433     public synchronized LegacyVpnInfo getLegacyVpnInfo() {
   1434         // Check if the caller is authorized.
   1435         enforceControlPermission();
   1436         return getLegacyVpnInfoPrivileged();
   1437     }
   1438 
   1439     /**
   1440      * Return the information of the current ongoing legacy VPN.
   1441      * Callers are responsible for checking permissions if needed.
   1442      */
   1443     public synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
   1444         if (mLegacyVpnRunner == null) return null;
   1445 
   1446         final LegacyVpnInfo info = new LegacyVpnInfo();
   1447         info.key = mConfig.user;
   1448         info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo);
   1449         if (mNetworkInfo.isConnected()) {
   1450             info.intent = mStatusIntent;
   1451         }
   1452         return info;
   1453     }
   1454 
   1455     public VpnConfig getLegacyVpnConfig() {
   1456         if (mLegacyVpnRunner != null) {
   1457             return mConfig;
   1458         } else {
   1459             return null;
   1460         }
   1461     }
   1462 
   1463     /**
   1464      * Bringing up a VPN connection takes time, and that is all this thread
   1465      * does. Here we have plenty of time. The only thing we need to take
   1466      * care of is responding to interruptions as soon as possible. Otherwise
   1467      * requests will be piled up. This can be done in a Handler as a state
   1468      * machine, but it is much easier to read in the current form.
   1469      */
   1470     private class LegacyVpnRunner extends Thread {
   1471         private static final String TAG = "LegacyVpnRunner";
   1472 
   1473         private final String[] mDaemons;
   1474         private final String[][] mArguments;
   1475         private final LocalSocket[] mSockets;
   1476         private final String mOuterInterface;
   1477         private final AtomicInteger mOuterConnection =
   1478                 new AtomicInteger(ConnectivityManager.TYPE_NONE);
   1479 
   1480         private long mTimer = -1;
   1481 
   1482         /**
   1483          * Watch for the outer connection (passing in the constructor) going away.
   1484          */
   1485         private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
   1486             @Override
   1487             public void onReceive(Context context, Intent intent) {
   1488                 if (!mEnableTeardown) return;
   1489 
   1490                 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
   1491                     if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
   1492                             ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) {
   1493                         NetworkInfo info = (NetworkInfo)intent.getExtra(
   1494                                 ConnectivityManager.EXTRA_NETWORK_INFO);
   1495                         if (info != null && !info.isConnectedOrConnecting()) {
   1496                             try {
   1497                                 mObserver.interfaceStatusChanged(mOuterInterface, false);
   1498                             } catch (RemoteException e) {}
   1499                         }
   1500                     }
   1501                 }
   1502             }
   1503         };
   1504 
   1505         public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
   1506             super(TAG);
   1507             mConfig = config;
   1508             mDaemons = new String[] {"racoon", "mtpd"};
   1509             // TODO: clear arguments from memory once launched
   1510             mArguments = new String[][] {racoon, mtpd};
   1511             mSockets = new LocalSocket[mDaemons.length];
   1512 
   1513             // This is the interface which VPN is running on,
   1514             // mConfig.interfaze will change to point to OUR
   1515             // internal interface soon. TODO - add inner/outer to mconfig
   1516             // TODO - we have a race - if the outer iface goes away/disconnects before we hit this
   1517             // we will leave the VPN up.  We should check that it's still there/connected after
   1518             // registering
   1519             mOuterInterface = mConfig.interfaze;
   1520 
   1521             if (!TextUtils.isEmpty(mOuterInterface)) {
   1522                 final ConnectivityManager cm = ConnectivityManager.from(mContext);
   1523                 for (Network network : cm.getAllNetworks()) {
   1524                     final LinkProperties lp = cm.getLinkProperties(network);
   1525                     if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) {
   1526                         final NetworkInfo networkInfo = cm.getNetworkInfo(network);
   1527                         if (networkInfo != null) mOuterConnection.set(networkInfo.getType());
   1528                     }
   1529                 }
   1530             }
   1531 
   1532             IntentFilter filter = new IntentFilter();
   1533             filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
   1534             mContext.registerReceiver(mBroadcastReceiver, filter);
   1535         }
   1536 
   1537         public void check(String interfaze) {
   1538             if (interfaze.equals(mOuterInterface)) {
   1539                 Log.i(TAG, "Legacy VPN is going down with " + interfaze);
   1540                 exit();
   1541             }
   1542         }
   1543 
   1544         public void exit() {
   1545             // We assume that everything is reset after stopping the daemons.
   1546             interrupt();
   1547             for (LocalSocket socket : mSockets) {
   1548                 IoUtils.closeQuietly(socket);
   1549             }
   1550             agentDisconnect();
   1551             try {
   1552                 mContext.unregisterReceiver(mBroadcastReceiver);
   1553             } catch (IllegalArgumentException e) {}
   1554         }
   1555 
   1556         @Override
   1557         public void run() {
   1558             // Wait for the previous thread since it has been interrupted.
   1559             Log.v(TAG, "Waiting");
   1560             synchronized (TAG) {
   1561                 Log.v(TAG, "Executing");
   1562                 execute();
   1563                 monitorDaemons();
   1564             }
   1565         }
   1566 
   1567         private void checkpoint(boolean yield) throws InterruptedException {
   1568             long now = SystemClock.elapsedRealtime();
   1569             if (mTimer == -1) {
   1570                 mTimer = now;
   1571                 Thread.sleep(1);
   1572             } else if (now - mTimer <= 60000) {
   1573                 Thread.sleep(yield ? 200 : 1);
   1574             } else {
   1575                 updateState(DetailedState.FAILED, "checkpoint");
   1576                 throw new IllegalStateException("Time is up");
   1577             }
   1578         }
   1579 
   1580         private void execute() {
   1581             // Catch all exceptions so we can clean up few things.
   1582             boolean initFinished = false;
   1583             try {
   1584                 // Initialize the timer.
   1585                 checkpoint(false);
   1586 
   1587                 // Wait for the daemons to stop.
   1588                 for (String daemon : mDaemons) {
   1589                     while (!SystemService.isStopped(daemon)) {
   1590                         checkpoint(true);
   1591                     }
   1592                 }
   1593 
   1594                 // Clear the previous state.
   1595                 File state = new File("/data/misc/vpn/state");
   1596                 state.delete();
   1597                 if (state.exists()) {
   1598                     throw new IllegalStateException("Cannot delete the state");
   1599                 }
   1600                 new File("/data/misc/vpn/abort").delete();
   1601                 initFinished = true;
   1602 
   1603                 // Check if we need to restart any of the daemons.
   1604                 boolean restart = false;
   1605                 for (String[] arguments : mArguments) {
   1606                     restart = restart || (arguments != null);
   1607                 }
   1608                 if (!restart) {
   1609                     agentDisconnect();
   1610                     return;
   1611                 }
   1612                 updateState(DetailedState.CONNECTING, "execute");
   1613 
   1614                 // Start the daemon with arguments.
   1615                 for (int i = 0; i < mDaemons.length; ++i) {
   1616                     String[] arguments = mArguments[i];
   1617                     if (arguments == null) {
   1618                         continue;
   1619                     }
   1620 
   1621                     // Start the daemon.
   1622                     String daemon = mDaemons[i];
   1623                     SystemService.start(daemon);
   1624 
   1625                     // Wait for the daemon to start.
   1626                     while (!SystemService.isRunning(daemon)) {
   1627                         checkpoint(true);
   1628                     }
   1629 
   1630                     // Create the control socket.
   1631                     mSockets[i] = new LocalSocket();
   1632                     LocalSocketAddress address = new LocalSocketAddress(
   1633                             daemon, LocalSocketAddress.Namespace.RESERVED);
   1634 
   1635                     // Wait for the socket to connect.
   1636                     while (true) {
   1637                         try {
   1638                             mSockets[i].connect(address);
   1639                             break;
   1640                         } catch (Exception e) {
   1641                             // ignore
   1642                         }
   1643                         checkpoint(true);
   1644                     }
   1645                     mSockets[i].setSoTimeout(500);
   1646 
   1647                     // Send over the arguments.
   1648                     OutputStream out = mSockets[i].getOutputStream();
   1649                     for (String argument : arguments) {
   1650                         byte[] bytes = argument.getBytes(StandardCharsets.UTF_8);
   1651                         if (bytes.length >= 0xFFFF) {
   1652                             throw new IllegalArgumentException("Argument is too large");
   1653                         }
   1654                         out.write(bytes.length >> 8);
   1655                         out.write(bytes.length);
   1656                         out.write(bytes);
   1657                         checkpoint(false);
   1658                     }
   1659                     out.write(0xFF);
   1660                     out.write(0xFF);
   1661                     out.flush();
   1662 
   1663                     // Wait for End-of-File.
   1664                     InputStream in = mSockets[i].getInputStream();
   1665                     while (true) {
   1666                         try {
   1667                             if (in.read() == -1) {
   1668                                 break;
   1669                             }
   1670                         } catch (Exception e) {
   1671                             // ignore
   1672                         }
   1673                         checkpoint(true);
   1674                     }
   1675                 }
   1676 
   1677                 // Wait for the daemons to create the new state.
   1678                 while (!state.exists()) {
   1679                     // Check if a running daemon is dead.
   1680                     for (int i = 0; i < mDaemons.length; ++i) {
   1681                         String daemon = mDaemons[i];
   1682                         if (mArguments[i] != null && !SystemService.isRunning(daemon)) {
   1683                             throw new IllegalStateException(daemon + " is dead");
   1684                         }
   1685                     }
   1686                     checkpoint(true);
   1687                 }
   1688 
   1689                 // Now we are connected. Read and parse the new state.
   1690                 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1);
   1691                 if (parameters.length != 7) {
   1692                     throw new IllegalStateException("Cannot parse the state");
   1693                 }
   1694 
   1695                 // Set the interface and the addresses in the config.
   1696                 mConfig.interfaze = parameters[0].trim();
   1697 
   1698                 mConfig.addLegacyAddresses(parameters[1]);
   1699                 // Set the routes if they are not set in the config.
   1700                 if (mConfig.routes == null || mConfig.routes.isEmpty()) {
   1701                     mConfig.addLegacyRoutes(parameters[2]);
   1702                 }
   1703 
   1704                 // Set the DNS servers if they are not set in the config.
   1705                 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) {
   1706                     String dnsServers = parameters[3].trim();
   1707                     if (!dnsServers.isEmpty()) {
   1708                         mConfig.dnsServers = Arrays.asList(dnsServers.split(" "));
   1709                     }
   1710                 }
   1711 
   1712                 // Set the search domains if they are not set in the config.
   1713                 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) {
   1714                     String searchDomains = parameters[4].trim();
   1715                     if (!searchDomains.isEmpty()) {
   1716                         mConfig.searchDomains = Arrays.asList(searchDomains.split(" "));
   1717                     }
   1718                 }
   1719 
   1720                 // Add a throw route for the VPN server endpoint, if one was specified.
   1721                 String endpoint = parameters[5];
   1722                 if (!endpoint.isEmpty()) {
   1723                     try {
   1724                         InetAddress addr = InetAddress.parseNumericAddress(endpoint);
   1725                         if (addr instanceof Inet4Address) {
   1726                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
   1727                         } else if (addr instanceof Inet6Address) {
   1728                             mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
   1729                         } else {
   1730                             Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
   1731                         }
   1732                     } catch (IllegalArgumentException e) {
   1733                         Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
   1734                     }
   1735                 }
   1736 
   1737                 // Here is the last step and it must be done synchronously.
   1738                 synchronized (Vpn.this) {
   1739                     // Set the start time
   1740                     mConfig.startTime = SystemClock.elapsedRealtime();
   1741 
   1742                     // Check if the thread is interrupted while we are waiting.
   1743                     checkpoint(false);
   1744 
   1745                     // Check if the interface is gone while we are waiting.
   1746                     if (jniCheck(mConfig.interfaze) == 0) {
   1747                         throw new IllegalStateException(mConfig.interfaze + " is gone");
   1748                     }
   1749 
   1750                     // Now INetworkManagementEventObserver is watching our back.
   1751                     mInterface = mConfig.interfaze;
   1752                     prepareStatusIntent();
   1753 
   1754                     agentConnect();
   1755 
   1756                     Log.i(TAG, "Connected!");
   1757                 }
   1758             } catch (Exception e) {
   1759                 Log.i(TAG, "Aborting", e);
   1760                 updateState(DetailedState.FAILED, e.getMessage());
   1761                 exit();
   1762             } finally {
   1763                 // Kill the daemons if they fail to stop.
   1764                 if (!initFinished) {
   1765                     for (String daemon : mDaemons) {
   1766                         SystemService.stop(daemon);
   1767                     }
   1768                 }
   1769 
   1770                 // Do not leave an unstable state.
   1771                 if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) {
   1772                     agentDisconnect();
   1773                 }
   1774             }
   1775         }
   1776 
   1777         /**
   1778          * Monitor the daemons we started, moving to disconnected state if the
   1779          * underlying services fail.
   1780          */
   1781         private void monitorDaemons() {
   1782             if (!mNetworkInfo.isConnected()) {
   1783                 return;
   1784             }
   1785 
   1786             try {
   1787                 while (true) {
   1788                     Thread.sleep(2000);
   1789                     for (int i = 0; i < mDaemons.length; i++) {
   1790                         if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) {
   1791                             return;
   1792                         }
   1793                     }
   1794                 }
   1795             } catch (InterruptedException e) {
   1796                 Log.d(TAG, "interrupted during monitorDaemons(); stopping services");
   1797             } finally {
   1798                 for (String daemon : mDaemons) {
   1799                     SystemService.stop(daemon);
   1800                 }
   1801 
   1802                 agentDisconnect();
   1803             }
   1804         }
   1805     }
   1806 }
   1807