Vpn.java revision 0784eeab28da094a87437ed454fe3dca01b1f9f2
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 17package com.android.server.connectivity; 18 19import static android.Manifest.permission.BIND_VPN_SERVICE; 20import static android.os.UserHandle.PER_USER_RANGE; 21import static android.system.OsConstants.AF_INET; 22import static android.system.OsConstants.AF_INET6; 23 24import android.app.AppGlobals; 25import android.app.AppOpsManager; 26import android.app.PendingIntent; 27import android.content.BroadcastReceiver; 28import android.content.ComponentName; 29import android.content.Context; 30import android.content.Intent; 31import android.content.IntentFilter; 32import android.content.ServiceConnection; 33import android.content.pm.ApplicationInfo; 34import android.content.pm.PackageManager; 35import android.content.pm.PackageManager.NameNotFoundException; 36import android.content.pm.ResolveInfo; 37import android.content.pm.UserInfo; 38import android.net.ConnectivityManager; 39import android.net.IConnectivityManager; 40import android.net.INetworkManagementEventObserver; 41import android.net.LinkAddress; 42import android.net.LinkProperties; 43import android.net.LocalSocket; 44import android.net.LocalSocketAddress; 45import android.net.NetworkAgent; 46import android.net.NetworkCapabilities; 47import android.net.NetworkInfo; 48import android.net.NetworkInfo.DetailedState; 49import android.net.NetworkMisc; 50import android.net.RouteInfo; 51import android.net.UidRange; 52import android.os.Binder; 53import android.os.FileUtils; 54import android.os.IBinder; 55import android.os.INetworkManagementService; 56import android.os.Looper; 57import android.os.Parcel; 58import android.os.ParcelFileDescriptor; 59import android.os.Process; 60import android.os.RemoteException; 61import android.os.SystemClock; 62import android.os.SystemService; 63import android.os.UserHandle; 64import android.os.UserManager; 65import android.security.Credentials; 66import android.security.KeyStore; 67import android.util.Log; 68 69import com.android.internal.annotations.GuardedBy; 70import com.android.internal.net.LegacyVpnInfo; 71import com.android.internal.net.VpnConfig; 72import com.android.internal.net.VpnProfile; 73import com.android.server.net.BaseNetworkObserver; 74 75import libcore.io.IoUtils; 76 77import java.io.File; 78import java.io.IOException; 79import java.io.InputStream; 80import java.io.OutputStream; 81import java.net.Inet4Address; 82import java.net.Inet6Address; 83import java.net.InetAddress; 84import java.nio.charset.StandardCharsets; 85import java.util.ArrayList; 86import java.util.Arrays; 87import java.util.List; 88import java.util.SortedSet; 89import java.util.TreeSet; 90import java.util.concurrent.atomic.AtomicInteger; 91 92/** 93 * @hide 94 */ 95public class Vpn { 96 private static final String NETWORKTYPE = "VPN"; 97 private static final String TAG = "Vpn"; 98 private static final boolean LOGD = true; 99 100 // TODO: create separate trackers for each unique VPN to support 101 // automated reconnection 102 103 private Context mContext; 104 private NetworkInfo mNetworkInfo; 105 private String mPackage; 106 private int mOwnerUID; 107 private String mInterface; 108 private boolean mAllowIPv4; 109 private boolean mAllowIPv6; 110 private Connection mConnection; 111 private LegacyVpnRunner mLegacyVpnRunner; 112 private PendingIntent mStatusIntent; 113 private volatile boolean mEnableTeardown = true; 114 private final IConnectivityManager mConnService; 115 private final INetworkManagementService mNetd; 116 private VpnConfig mConfig; 117 private NetworkAgent mNetworkAgent; 118 private final Looper mLooper; 119 private final NetworkCapabilities mNetworkCapabilities; 120 121 /* list of users using this VPN. */ 122 @GuardedBy("this") 123 private List<UidRange> mVpnUsers = null; 124 private BroadcastReceiver mUserIntentReceiver = null; 125 126 // Handle of user initiating VPN. 127 private final int mUserHandle; 128 129 public Vpn(Looper looper, Context context, INetworkManagementService netService, 130 IConnectivityManager connService, int userHandle) { 131 mContext = context; 132 mNetd = netService; 133 mConnService = connService; 134 mUserHandle = userHandle; 135 mLooper = looper; 136 137 mPackage = VpnConfig.LEGACY_VPN; 138 mOwnerUID = getAppUid(mPackage, mUserHandle); 139 140 try { 141 netService.registerObserver(mObserver); 142 } catch (RemoteException e) { 143 Log.wtf(TAG, "Problem registering observer", e); 144 } 145 if (userHandle == UserHandle.USER_OWNER) { 146 // Owner's VPN also needs to handle restricted users 147 mUserIntentReceiver = new BroadcastReceiver() { 148 @Override 149 public void onReceive(Context context, Intent intent) { 150 final String action = intent.getAction(); 151 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 152 UserHandle.USER_NULL); 153 if (userHandle == UserHandle.USER_NULL) return; 154 155 if (Intent.ACTION_USER_ADDED.equals(action)) { 156 onUserAdded(userHandle); 157 } else if (Intent.ACTION_USER_REMOVED.equals(action)) { 158 onUserRemoved(userHandle); 159 } 160 } 161 }; 162 163 IntentFilter intentFilter = new IntentFilter(); 164 intentFilter.addAction(Intent.ACTION_USER_ADDED); 165 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 166 mContext.registerReceiverAsUser( 167 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null); 168 } 169 170 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0, NETWORKTYPE, ""); 171 // TODO: Copy metered attribute and bandwidths from physical transport, b/16207332 172 mNetworkCapabilities = new NetworkCapabilities(); 173 mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); 174 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); 175 } 176 177 /** 178 * Set if this object is responsible for watching for {@link NetworkInfo} 179 * teardown. When {@code false}, teardown is handled externally by someone 180 * else. 181 */ 182 public void setEnableTeardown(boolean enableTeardown) { 183 mEnableTeardown = enableTeardown; 184 } 185 186 /** 187 * Update current state, dispaching event to listeners. 188 */ 189 private void updateState(DetailedState detailedState, String reason) { 190 if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); 191 mNetworkInfo.setDetailedState(detailedState, reason, null); 192 if (mNetworkAgent != null) { 193 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 194 } 195 } 196 197 /** 198 * Prepare for a VPN application. This method is designed to solve 199 * race conditions. It first compares the current prepared package 200 * with {@code oldPackage}. If they are the same, the prepared 201 * package is revoked and replaced with {@code newPackage}. If 202 * {@code oldPackage} is {@code null}, the comparison is omitted. 203 * If {@code newPackage} is the same package or {@code null}, the 204 * revocation is omitted. This method returns {@code true} if the 205 * operation is succeeded. 206 * 207 * Legacy VPN is handled specially since it is not a real package. 208 * It uses {@link VpnConfig#LEGACY_VPN} as its package name, and 209 * it can be revoked by itself. 210 * 211 * @param oldPackage The package name of the old VPN application. 212 * @param newPackage The package name of the new VPN application. 213 * @return true if the operation is succeeded. 214 */ 215 public synchronized boolean prepare(String oldPackage, String newPackage) { 216 // Return false if the package does not match. 217 if (oldPackage != null && !oldPackage.equals(mPackage)) { 218 // The package doesn't match. If this VPN was not previously authorized, return false 219 // to force user authorization. Otherwise, revoke the VPN anyway. 220 if (!oldPackage.equals(VpnConfig.LEGACY_VPN) && isVpnUserPreConsented(oldPackage)) { 221 long token = Binder.clearCallingIdentity(); 222 try { 223 // This looks bizarre, but it is what ConfirmDialog in VpnDialogs is doing when 224 // the user clicks through to allow the VPN to consent. So we are emulating the 225 // action of the dialog without actually showing it. 226 prepare(null, oldPackage); 227 } finally { 228 Binder.restoreCallingIdentity(token); 229 } 230 return true; 231 } 232 return false; 233 } 234 235 // Return true if we do not need to revoke. 236 if (newPackage == null || 237 (newPackage.equals(mPackage) && !newPackage.equals(VpnConfig.LEGACY_VPN))) { 238 return true; 239 } 240 241 // Check if the caller is authorized. 242 enforceControlPermission(); 243 244 // Reset the interface. 245 if (mInterface != null) { 246 mStatusIntent = null; 247 agentDisconnect(); 248 jniReset(mInterface); 249 mInterface = null; 250 mVpnUsers = null; 251 } 252 253 // Revoke the connection or stop LegacyVpnRunner. 254 if (mConnection != null) { 255 try { 256 mConnection.mService.transact(IBinder.LAST_CALL_TRANSACTION, 257 Parcel.obtain(), null, IBinder.FLAG_ONEWAY); 258 } catch (Exception e) { 259 // ignore 260 } 261 mContext.unbindService(mConnection); 262 mConnection = null; 263 } else if (mLegacyVpnRunner != null) { 264 mLegacyVpnRunner.exit(); 265 mLegacyVpnRunner = null; 266 } 267 268 long token = Binder.clearCallingIdentity(); 269 try { 270 mNetd.denyProtect(mOwnerUID); 271 } catch (Exception e) { 272 Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e); 273 } finally { 274 Binder.restoreCallingIdentity(token); 275 } 276 277 Log.i(TAG, "Switched from " + mPackage + " to " + newPackage); 278 mPackage = newPackage; 279 mOwnerUID = getAppUid(newPackage, mUserHandle); 280 token = Binder.clearCallingIdentity(); 281 try { 282 mNetd.allowProtect(mOwnerUID); 283 } catch (Exception e) { 284 Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e); 285 } finally { 286 Binder.restoreCallingIdentity(token); 287 } 288 mConfig = null; 289 290 updateState(DetailedState.IDLE, "prepare"); 291 return true; 292 } 293 294 /** 295 * Set whether the current package has the ability to launch VPNs without user intervention. 296 */ 297 public void setPackageAuthorization(boolean authorized) { 298 // Check if the caller is authorized. 299 enforceControlPermission(); 300 301 if (mPackage == null || VpnConfig.LEGACY_VPN.equals(mPackage)) { 302 return; 303 } 304 305 long token = Binder.clearCallingIdentity(); 306 try { 307 AppOpsManager appOps = 308 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 309 appOps.setMode(AppOpsManager.OP_ACTIVATE_VPN, mOwnerUID, mPackage, 310 authorized ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); 311 } catch (Exception e) { 312 Log.wtf(TAG, "Failed to set app ops for package " + mPackage, e); 313 } finally { 314 Binder.restoreCallingIdentity(token); 315 } 316 } 317 318 private boolean isVpnUserPreConsented(String packageName) { 319 AppOpsManager appOps = 320 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 321 322 // Verify that the caller matches the given package and has permission to activate VPNs. 323 return appOps.noteOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN, Binder.getCallingUid(), 324 packageName) == AppOpsManager.MODE_ALLOWED; 325 } 326 327 private int getAppUid(String app, int userHandle) { 328 if (VpnConfig.LEGACY_VPN.equals(app)) { 329 return Process.myUid(); 330 } 331 PackageManager pm = mContext.getPackageManager(); 332 int result; 333 try { 334 result = pm.getPackageUid(app, userHandle); 335 } catch (NameNotFoundException e) { 336 result = -1; 337 } 338 return result; 339 } 340 341 public NetworkInfo getNetworkInfo() { 342 return mNetworkInfo; 343 } 344 345 private void agentConnect() { 346 LinkProperties lp = new LinkProperties(); 347 lp.setInterfaceName(mInterface); 348 349 boolean hasDefaultRoute = false; 350 for (RouteInfo route : mConfig.routes) { 351 lp.addRoute(route); 352 if (route.isDefaultRoute()) hasDefaultRoute = true; 353 } 354 if (hasDefaultRoute) { 355 mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 356 } else { 357 mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 358 } 359 360 if (mConfig.dnsServers != null) { 361 for (String dnsServer : mConfig.dnsServers) { 362 InetAddress address = InetAddress.parseNumericAddress(dnsServer); 363 lp.addDnsServer(address); 364 if (address instanceof Inet4Address) { 365 mAllowIPv4 = true; 366 } else { 367 mAllowIPv6 = true; 368 } 369 } 370 } 371 372 // Concatenate search domains into a string. 373 StringBuilder buffer = new StringBuilder(); 374 if (mConfig.searchDomains != null) { 375 for (String domain : mConfig.searchDomains) { 376 buffer.append(domain).append(' '); 377 } 378 } 379 lp.setDomains(buffer.toString().trim()); 380 381 mNetworkInfo.setIsAvailable(true); 382 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 383 384 NetworkMisc networkMisc = new NetworkMisc(); 385 networkMisc.allowBypass = mConfig.allowBypass; 386 387 long token = Binder.clearCallingIdentity(); 388 try { 389 mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE, 390 mNetworkInfo, mNetworkCapabilities, lp, 0, networkMisc) { 391 @Override 392 public void unwanted() { 393 // We are user controlled, not driven by NetworkRequest. 394 } 395 }; 396 } finally { 397 Binder.restoreCallingIdentity(token); 398 } 399 400 if (!mAllowIPv4) { 401 mNetworkAgent.blockAddressFamily(AF_INET); 402 } 403 if (!mAllowIPv6) { 404 mNetworkAgent.blockAddressFamily(AF_INET6); 405 } 406 407 addVpnUserLocked(mUserHandle); 408 // If we are owner assign all Restricted Users to this VPN 409 if (mUserHandle == UserHandle.USER_OWNER) { 410 token = Binder.clearCallingIdentity(); 411 List<UserInfo> users; 412 try { 413 users = UserManager.get(mContext).getUsers(); 414 } finally { 415 Binder.restoreCallingIdentity(token); 416 } 417 for (UserInfo user : users) { 418 if (user.isRestricted()) { 419 addVpnUserLocked(user.id); 420 } 421 } 422 } 423 mNetworkAgent.addUidRanges(mVpnUsers.toArray(new UidRange[mVpnUsers.size()])); 424 } 425 426 private void agentDisconnect(NetworkInfo networkInfo, NetworkAgent networkAgent) { 427 networkInfo.setIsAvailable(false); 428 networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 429 if (networkAgent != null) { 430 networkAgent.sendNetworkInfo(networkInfo); 431 } 432 } 433 434 private void agentDisconnect(NetworkAgent networkAgent) { 435 NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); 436 agentDisconnect(networkInfo, networkAgent); 437 } 438 439 private void agentDisconnect() { 440 if (mNetworkInfo.isConnected()) { 441 agentDisconnect(mNetworkInfo, mNetworkAgent); 442 mNetworkAgent = null; 443 } 444 } 445 446 /** 447 * Establish a VPN network and return the file descriptor of the VPN 448 * interface. This methods returns {@code null} if the application is 449 * revoked or not prepared. 450 * 451 * @param config The parameters to configure the network. 452 * @return The file descriptor of the VPN interface. 453 */ 454 public synchronized ParcelFileDescriptor establish(VpnConfig config) { 455 // Check if the caller is already prepared. 456 UserManager mgr = UserManager.get(mContext); 457 if (Binder.getCallingUid() != mOwnerUID) { 458 return null; 459 } 460 // Check if the service is properly declared. 461 Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE); 462 intent.setClassName(mPackage, config.user); 463 long token = Binder.clearCallingIdentity(); 464 try { 465 // Restricted users are not allowed to create VPNs, they are tied to Owner 466 UserInfo user = mgr.getUserInfo(mUserHandle); 467 if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { 468 throw new SecurityException("Restricted users cannot establish VPNs"); 469 } 470 471 ResolveInfo info = AppGlobals.getPackageManager().resolveService(intent, 472 null, 0, mUserHandle); 473 if (info == null) { 474 throw new SecurityException("Cannot find " + config.user); 475 } 476 if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) { 477 throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE); 478 } 479 } catch (RemoteException e) { 480 throw new SecurityException("Cannot find " + config.user); 481 } finally { 482 Binder.restoreCallingIdentity(token); 483 } 484 485 // Save the old config in case we need to go back. 486 VpnConfig oldConfig = mConfig; 487 String oldInterface = mInterface; 488 Connection oldConnection = mConnection; 489 NetworkAgent oldNetworkAgent = mNetworkAgent; 490 mNetworkAgent = null; 491 List<UidRange> oldUsers = mVpnUsers; 492 boolean oldAllowIPv4 = mAllowIPv4; 493 boolean oldAllowIPv6 = mAllowIPv6; 494 495 // Configure the interface. Abort if any of these steps fails. 496 ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); 497 try { 498 updateState(DetailedState.CONNECTING, "establish"); 499 String interfaze = jniGetName(tun.getFd()); 500 501 // TEMP use the old jni calls until there is support for netd address setting 502 StringBuilder builder = new StringBuilder(); 503 for (LinkAddress address : config.addresses) { 504 builder.append(" " + address); 505 } 506 if (jniSetAddresses(interfaze, builder.toString()) < 1) { 507 throw new IllegalArgumentException("At least one address must be specified"); 508 } 509 Connection connection = new Connection(); 510 if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE, 511 new UserHandle(mUserHandle))) { 512 throw new IllegalStateException("Cannot bind " + config.user); 513 } 514 515 mConnection = connection; 516 mInterface = interfaze; 517 518 // Fill more values. 519 config.user = mPackage; 520 config.interfaze = mInterface; 521 config.startTime = SystemClock.elapsedRealtime(); 522 mConfig = config; 523 524 // Set up forwarding and DNS rules. 525 mVpnUsers = new ArrayList<UidRange>(); 526 mAllowIPv4 = mConfig.allowIPv4; 527 mAllowIPv6 = mConfig.allowIPv6; 528 529 agentConnect(); 530 531 if (oldConnection != null) { 532 mContext.unbindService(oldConnection); 533 } 534 // Remove the old tun's user forwarding rules 535 // The new tun's user rules have already been added so they will take over 536 // as rules are deleted. This prevents data leakage as the rules are moved over. 537 agentDisconnect(oldNetworkAgent); 538 if (oldInterface != null && !oldInterface.equals(interfaze)) { 539 jniReset(oldInterface); 540 } 541 542 try { 543 IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking); 544 } catch (IOException e) { 545 throw new IllegalStateException( 546 "Cannot set tunnel's fd as blocking=" + config.blocking, e); 547 } 548 } catch (RuntimeException e) { 549 IoUtils.closeQuietly(tun); 550 agentDisconnect(); 551 // restore old state 552 mConfig = oldConfig; 553 mConnection = oldConnection; 554 mVpnUsers = oldUsers; 555 mNetworkAgent = oldNetworkAgent; 556 mInterface = oldInterface; 557 mAllowIPv4 = oldAllowIPv4; 558 mAllowIPv6 = oldAllowIPv6; 559 throw e; 560 } 561 Log.i(TAG, "Established by " + config.user + " on " + mInterface); 562 return tun; 563 } 564 565 private boolean isRunningLocked() { 566 return mVpnUsers != null; 567 } 568 569 // Note: Return type guarantees results are deduped and sorted, which callers require. 570 private SortedSet<Integer> getAppsUids(List<String> packageNames, int userHandle) { 571 SortedSet<Integer> uids = new TreeSet<Integer>(); 572 for (String app : packageNames) { 573 int uid = getAppUid(app, userHandle); 574 if (uid != -1) uids.add(uid); 575 } 576 return uids; 577 } 578 579 // Note: This function adds to mVpnUsers but does not publish list to NetworkAgent. 580 private void addVpnUserLocked(int userHandle) { 581 if (!isRunningLocked()) { 582 throw new IllegalStateException("VPN is not active"); 583 } 584 585 if (mConfig.allowedApplications != null) { 586 // Add ranges covering all UIDs for allowedApplications. 587 int start = -1, stop = -1; 588 for (int uid : getAppsUids(mConfig.allowedApplications, userHandle)) { 589 if (start == -1) { 590 start = uid; 591 } else if (uid != stop + 1) { 592 mVpnUsers.add(new UidRange(start, stop)); 593 start = uid; 594 } 595 stop = uid; 596 } 597 if (start != -1) mVpnUsers.add(new UidRange(start, stop)); 598 } else if (mConfig.disallowedApplications != null) { 599 // Add all ranges for user skipping UIDs for disallowedApplications. 600 final UidRange userRange = UidRange.createForUser(userHandle); 601 int start = userRange.start; 602 for (int uid : getAppsUids(mConfig.disallowedApplications, userHandle)) { 603 if (uid == start) { 604 start++; 605 } else { 606 mVpnUsers.add(new UidRange(start, uid - 1)); 607 start = uid + 1; 608 } 609 } 610 if (start <= userRange.stop) mVpnUsers.add(new UidRange(start, userRange.stop)); 611 } else { 612 // Add all UIDs for the user. 613 mVpnUsers.add(UidRange.createForUser(userHandle)); 614 } 615 616 prepareStatusIntent(); 617 } 618 619 // Returns the subset of the full list of active UID ranges the VPN applies to (mVpnUsers) that 620 // apply to userHandle. 621 private List<UidRange> uidRangesForUser(int userHandle) { 622 final UidRange userRange = UidRange.createForUser(userHandle); 623 final List<UidRange> ranges = new ArrayList<UidRange>(); 624 for (UidRange range : mVpnUsers) { 625 if (range.start >= userRange.start && range.stop <= userRange.stop) { 626 ranges.add(range); 627 } 628 } 629 return ranges; 630 } 631 632 private void removeVpnUserLocked(int userHandle) { 633 if (!isRunningLocked()) { 634 throw new IllegalStateException("VPN is not active"); 635 } 636 final List<UidRange> ranges = uidRangesForUser(userHandle); 637 if (mNetworkAgent != null) { 638 mNetworkAgent.removeUidRanges(ranges.toArray(new UidRange[ranges.size()])); 639 } 640 mVpnUsers.removeAll(ranges); 641 mStatusIntent = null; 642 } 643 644 private void onUserAdded(int userHandle) { 645 // If the user is restricted tie them to the owner's VPN 646 synchronized(Vpn.this) { 647 UserManager mgr = UserManager.get(mContext); 648 UserInfo user = mgr.getUserInfo(userHandle); 649 if (user.isRestricted()) { 650 try { 651 addVpnUserLocked(userHandle); 652 if (mNetworkAgent != null) { 653 final List<UidRange> ranges = uidRangesForUser(userHandle); 654 mNetworkAgent.addUidRanges(ranges.toArray(new UidRange[ranges.size()])); 655 } 656 } catch (Exception e) { 657 Log.wtf(TAG, "Failed to add restricted user to owner", e); 658 } 659 } 660 } 661 } 662 663 private void onUserRemoved(int userHandle) { 664 // clean up if restricted 665 synchronized(Vpn.this) { 666 UserManager mgr = UserManager.get(mContext); 667 UserInfo user = mgr.getUserInfo(userHandle); 668 if (user.isRestricted()) { 669 try { 670 removeVpnUserLocked(userHandle); 671 } catch (Exception e) { 672 Log.wtf(TAG, "Failed to remove restricted user to owner", e); 673 } 674 } 675 } 676 } 677 678 /** 679 * Return the configuration of the currently running VPN. 680 */ 681 public VpnConfig getVpnConfig() { 682 enforceControlPermission(); 683 return mConfig; 684 } 685 686 @Deprecated 687 public synchronized void interfaceStatusChanged(String iface, boolean up) { 688 try { 689 mObserver.interfaceStatusChanged(iface, up); 690 } catch (RemoteException e) { 691 // ignored; target is local 692 } 693 } 694 695 private INetworkManagementEventObserver mObserver = new BaseNetworkObserver() { 696 @Override 697 public void interfaceStatusChanged(String interfaze, boolean up) { 698 synchronized (Vpn.this) { 699 if (!up && mLegacyVpnRunner != null) { 700 mLegacyVpnRunner.check(interfaze); 701 } 702 } 703 } 704 705 @Override 706 public void interfaceRemoved(String interfaze) { 707 synchronized (Vpn.this) { 708 if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { 709 mStatusIntent = null; 710 mVpnUsers = null; 711 mInterface = null; 712 if (mConnection != null) { 713 mContext.unbindService(mConnection); 714 mConnection = null; 715 agentDisconnect(); 716 } else if (mLegacyVpnRunner != null) { 717 mLegacyVpnRunner.exit(); 718 mLegacyVpnRunner = null; 719 } 720 } 721 } 722 } 723 }; 724 725 private void enforceControlPermission() { 726 // System user is allowed to control VPN. 727 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 728 return; 729 } 730 int appId = UserHandle.getAppId(Binder.getCallingUid()); 731 final long token = Binder.clearCallingIdentity(); 732 try { 733 // System VPN dialogs are also allowed to control VPN. 734 PackageManager pm = mContext.getPackageManager(); 735 ApplicationInfo app = pm.getApplicationInfo(VpnConfig.DIALOGS_PACKAGE, 0); 736 if (((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == app.uid)) { 737 return; 738 } 739 // SystemUI dialogs are also allowed to control VPN. 740 ApplicationInfo sysUiApp = pm.getApplicationInfo("com.android.systemui", 0); 741 if (((sysUiApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == sysUiApp.uid)) { 742 return; 743 } 744 } catch (Exception e) { 745 // ignore 746 } finally { 747 Binder.restoreCallingIdentity(token); 748 } 749 750 throw new SecurityException("Unauthorized Caller"); 751 } 752 753 private class Connection implements ServiceConnection { 754 private IBinder mService; 755 756 @Override 757 public void onServiceConnected(ComponentName name, IBinder service) { 758 mService = service; 759 } 760 761 @Override 762 public void onServiceDisconnected(ComponentName name) { 763 mService = null; 764 } 765 } 766 767 private void prepareStatusIntent() { 768 final long token = Binder.clearCallingIdentity(); 769 try { 770 mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext); 771 } finally { 772 Binder.restoreCallingIdentity(token); 773 } 774 } 775 776 public synchronized boolean addAddress(String address, int prefixLength) { 777 if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) { 778 return false; 779 } 780 boolean success = jniAddAddress(mInterface, address, prefixLength); 781 if (success && (!mAllowIPv4 || !mAllowIPv6)) { 782 try { 783 InetAddress inetAddress = InetAddress.parseNumericAddress(address); 784 if ((inetAddress instanceof Inet4Address) && !mAllowIPv4) { 785 mAllowIPv4 = true; 786 mNetworkAgent.unblockAddressFamily(AF_INET); 787 } else if ((inetAddress instanceof Inet6Address) && !mAllowIPv6) { 788 mAllowIPv6 = true; 789 mNetworkAgent.unblockAddressFamily(AF_INET6); 790 } 791 } catch (IllegalArgumentException e) { 792 // ignore 793 } 794 } 795 // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService 796 // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set 797 // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect()) 798 // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()). 799 // TODO: Maybe fix this. 800 return success; 801 } 802 803 public synchronized boolean removeAddress(String address, int prefixLength) { 804 if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) { 805 return false; 806 } 807 boolean success = jniDelAddress(mInterface, address, prefixLength); 808 // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService 809 // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set 810 // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect()) 811 // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()). 812 // TODO: Maybe fix this. 813 return success; 814 } 815 816 private native int jniCreate(int mtu); 817 private native String jniGetName(int tun); 818 private native int jniSetAddresses(String interfaze, String addresses); 819 private native void jniReset(String interfaze); 820 private native int jniCheck(String interfaze); 821 private native boolean jniAddAddress(String interfaze, String address, int prefixLen); 822 private native boolean jniDelAddress(String interfaze, String address, int prefixLen); 823 824 private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { 825 for (RouteInfo route : prop.getAllRoutes()) { 826 // Currently legacy VPN only works on IPv4. 827 if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { 828 return route; 829 } 830 } 831 832 throw new IllegalStateException("Unable to find IPv4 default gateway"); 833 } 834 835 /** 836 * Start legacy VPN, controlling native daemons as needed. Creates a 837 * secondary thread to perform connection work, returning quickly. 838 */ 839 public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) { 840 enforceControlPermission(); 841 if (!keyStore.isUnlocked()) { 842 throw new IllegalStateException("KeyStore isn't unlocked"); 843 } 844 UserManager mgr = UserManager.get(mContext); 845 UserInfo user = mgr.getUserInfo(mUserHandle); 846 if (user.isRestricted() || mgr.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { 847 throw new SecurityException("Restricted users cannot establish VPNs"); 848 } 849 850 final RouteInfo ipv4DefaultRoute = findIPv4DefaultRoute(egress); 851 final String gateway = ipv4DefaultRoute.getGateway().getHostAddress(); 852 final String iface = ipv4DefaultRoute.getInterface(); 853 854 // Load certificates. 855 String privateKey = ""; 856 String userCert = ""; 857 String caCert = ""; 858 String serverCert = ""; 859 if (!profile.ipsecUserCert.isEmpty()) { 860 privateKey = Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert; 861 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert); 862 userCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 863 } 864 if (!profile.ipsecCaCert.isEmpty()) { 865 byte[] value = keyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert); 866 caCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 867 } 868 if (!profile.ipsecServerCert.isEmpty()) { 869 byte[] value = keyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert); 870 serverCert = (value == null) ? null : new String(value, StandardCharsets.UTF_8); 871 } 872 if (privateKey == null || userCert == null || caCert == null || serverCert == null) { 873 throw new IllegalStateException("Cannot load credentials"); 874 } 875 876 // Prepare arguments for racoon. 877 String[] racoon = null; 878 switch (profile.type) { 879 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 880 racoon = new String[] { 881 iface, profile.server, "udppsk", profile.ipsecIdentifier, 882 profile.ipsecSecret, "1701", 883 }; 884 break; 885 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 886 racoon = new String[] { 887 iface, profile.server, "udprsa", privateKey, userCert, 888 caCert, serverCert, "1701", 889 }; 890 break; 891 case VpnProfile.TYPE_IPSEC_XAUTH_PSK: 892 racoon = new String[] { 893 iface, profile.server, "xauthpsk", profile.ipsecIdentifier, 894 profile.ipsecSecret, profile.username, profile.password, "", gateway, 895 }; 896 break; 897 case VpnProfile.TYPE_IPSEC_XAUTH_RSA: 898 racoon = new String[] { 899 iface, profile.server, "xauthrsa", privateKey, userCert, 900 caCert, serverCert, profile.username, profile.password, "", gateway, 901 }; 902 break; 903 case VpnProfile.TYPE_IPSEC_HYBRID_RSA: 904 racoon = new String[] { 905 iface, profile.server, "hybridrsa", 906 caCert, serverCert, profile.username, profile.password, "", gateway, 907 }; 908 break; 909 } 910 911 // Prepare arguments for mtpd. 912 String[] mtpd = null; 913 switch (profile.type) { 914 case VpnProfile.TYPE_PPTP: 915 mtpd = new String[] { 916 iface, "pptp", profile.server, "1723", 917 "name", profile.username, "password", profile.password, 918 "linkname", "vpn", "refuse-eap", "nodefaultroute", 919 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 920 (profile.mppe ? "+mppe" : "nomppe"), 921 }; 922 break; 923 case VpnProfile.TYPE_L2TP_IPSEC_PSK: 924 case VpnProfile.TYPE_L2TP_IPSEC_RSA: 925 mtpd = new String[] { 926 iface, "l2tp", profile.server, "1701", profile.l2tpSecret, 927 "name", profile.username, "password", profile.password, 928 "linkname", "vpn", "refuse-eap", "nodefaultroute", 929 "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 930 }; 931 break; 932 } 933 934 VpnConfig config = new VpnConfig(); 935 config.legacy = true; 936 config.user = profile.key; 937 config.interfaze = iface; 938 config.session = profile.name; 939 940 config.addLegacyRoutes(profile.routes); 941 if (!profile.dnsServers.isEmpty()) { 942 config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); 943 } 944 if (!profile.searchDomains.isEmpty()) { 945 config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); 946 } 947 startLegacyVpn(config, racoon, mtpd); 948 } 949 950 private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { 951 stopLegacyVpn(); 952 953 // Prepare for the new request. This also checks the caller. 954 prepare(null, VpnConfig.LEGACY_VPN); 955 updateState(DetailedState.CONNECTING, "startLegacyVpn"); 956 957 // Start a new LegacyVpnRunner and we are done! 958 mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd); 959 mLegacyVpnRunner.start(); 960 } 961 962 public synchronized void stopLegacyVpn() { 963 if (mLegacyVpnRunner != null) { 964 mLegacyVpnRunner.exit(); 965 mLegacyVpnRunner = null; 966 967 synchronized (LegacyVpnRunner.TAG) { 968 // wait for old thread to completely finish before spinning up 969 // new instance, otherwise state updates can be out of order. 970 } 971 } 972 } 973 974 /** 975 * Return the information of the current ongoing legacy VPN. 976 */ 977 public synchronized LegacyVpnInfo getLegacyVpnInfo() { 978 // Check if the caller is authorized. 979 enforceControlPermission(); 980 if (mLegacyVpnRunner == null) return null; 981 982 final LegacyVpnInfo info = new LegacyVpnInfo(); 983 info.key = mConfig.user; 984 info.state = LegacyVpnInfo.stateFromNetworkInfo(mNetworkInfo); 985 if (mNetworkInfo.isConnected()) { 986 info.intent = mStatusIntent; 987 } 988 return info; 989 } 990 991 public VpnConfig getLegacyVpnConfig() { 992 if (mLegacyVpnRunner != null) { 993 return mConfig; 994 } else { 995 return null; 996 } 997 } 998 999 /** 1000 * Bringing up a VPN connection takes time, and that is all this thread 1001 * does. Here we have plenty of time. The only thing we need to take 1002 * care of is responding to interruptions as soon as possible. Otherwise 1003 * requests will be piled up. This can be done in a Handler as a state 1004 * machine, but it is much easier to read in the current form. 1005 */ 1006 private class LegacyVpnRunner extends Thread { 1007 private static final String TAG = "LegacyVpnRunner"; 1008 1009 private final String[] mDaemons; 1010 private final String[][] mArguments; 1011 private final LocalSocket[] mSockets; 1012 private final String mOuterInterface; 1013 private final AtomicInteger mOuterConnection = 1014 new AtomicInteger(ConnectivityManager.TYPE_NONE); 1015 1016 private long mTimer = -1; 1017 1018 /** 1019 * Watch for the outer connection (passing in the constructor) going away. 1020 */ 1021 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 1022 @Override 1023 public void onReceive(Context context, Intent intent) { 1024 if (!mEnableTeardown) return; 1025 1026 if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 1027 if (intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, 1028 ConnectivityManager.TYPE_NONE) == mOuterConnection.get()) { 1029 NetworkInfo info = (NetworkInfo)intent.getExtra( 1030 ConnectivityManager.EXTRA_NETWORK_INFO); 1031 if (info != null && !info.isConnectedOrConnecting()) { 1032 try { 1033 mObserver.interfaceStatusChanged(mOuterInterface, false); 1034 } catch (RemoteException e) {} 1035 } 1036 } 1037 } 1038 } 1039 }; 1040 1041 public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) { 1042 super(TAG); 1043 mConfig = config; 1044 mDaemons = new String[] {"racoon", "mtpd"}; 1045 // TODO: clear arguments from memory once launched 1046 mArguments = new String[][] {racoon, mtpd}; 1047 mSockets = new LocalSocket[mDaemons.length]; 1048 1049 // This is the interface which VPN is running on, 1050 // mConfig.interfaze will change to point to OUR 1051 // internal interface soon. TODO - add inner/outer to mconfig 1052 // TODO - we have a race - if the outer iface goes away/disconnects before we hit this 1053 // we will leave the VPN up. We should check that it's still there/connected after 1054 // registering 1055 mOuterInterface = mConfig.interfaze; 1056 1057 try { 1058 mOuterConnection.set( 1059 mConnService.findConnectionTypeForIface(mOuterInterface)); 1060 } catch (Exception e) { 1061 mOuterConnection.set(ConnectivityManager.TYPE_NONE); 1062 } 1063 1064 IntentFilter filter = new IntentFilter(); 1065 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 1066 mContext.registerReceiver(mBroadcastReceiver, filter); 1067 } 1068 1069 public void check(String interfaze) { 1070 if (interfaze.equals(mOuterInterface)) { 1071 Log.i(TAG, "Legacy VPN is going down with " + interfaze); 1072 exit(); 1073 } 1074 } 1075 1076 public void exit() { 1077 // We assume that everything is reset after stopping the daemons. 1078 interrupt(); 1079 for (LocalSocket socket : mSockets) { 1080 IoUtils.closeQuietly(socket); 1081 } 1082 agentDisconnect(); 1083 try { 1084 mContext.unregisterReceiver(mBroadcastReceiver); 1085 } catch (IllegalArgumentException e) {} 1086 } 1087 1088 @Override 1089 public void run() { 1090 // Wait for the previous thread since it has been interrupted. 1091 Log.v(TAG, "Waiting"); 1092 synchronized (TAG) { 1093 Log.v(TAG, "Executing"); 1094 execute(); 1095 monitorDaemons(); 1096 } 1097 } 1098 1099 private void checkpoint(boolean yield) throws InterruptedException { 1100 long now = SystemClock.elapsedRealtime(); 1101 if (mTimer == -1) { 1102 mTimer = now; 1103 Thread.sleep(1); 1104 } else if (now - mTimer <= 60000) { 1105 Thread.sleep(yield ? 200 : 1); 1106 } else { 1107 updateState(DetailedState.FAILED, "checkpoint"); 1108 throw new IllegalStateException("Time is up"); 1109 } 1110 } 1111 1112 private void execute() { 1113 // Catch all exceptions so we can clean up few things. 1114 boolean initFinished = false; 1115 try { 1116 // Initialize the timer. 1117 checkpoint(false); 1118 1119 // Wait for the daemons to stop. 1120 for (String daemon : mDaemons) { 1121 while (!SystemService.isStopped(daemon)) { 1122 checkpoint(true); 1123 } 1124 } 1125 1126 // Clear the previous state. 1127 File state = new File("/data/misc/vpn/state"); 1128 state.delete(); 1129 if (state.exists()) { 1130 throw new IllegalStateException("Cannot delete the state"); 1131 } 1132 new File("/data/misc/vpn/abort").delete(); 1133 initFinished = true; 1134 1135 // Check if we need to restart any of the daemons. 1136 boolean restart = false; 1137 for (String[] arguments : mArguments) { 1138 restart = restart || (arguments != null); 1139 } 1140 if (!restart) { 1141 agentDisconnect(); 1142 return; 1143 } 1144 updateState(DetailedState.CONNECTING, "execute"); 1145 1146 // Start the daemon with arguments. 1147 for (int i = 0; i < mDaemons.length; ++i) { 1148 String[] arguments = mArguments[i]; 1149 if (arguments == null) { 1150 continue; 1151 } 1152 1153 // Start the daemon. 1154 String daemon = mDaemons[i]; 1155 SystemService.start(daemon); 1156 1157 // Wait for the daemon to start. 1158 while (!SystemService.isRunning(daemon)) { 1159 checkpoint(true); 1160 } 1161 1162 // Create the control socket. 1163 mSockets[i] = new LocalSocket(); 1164 LocalSocketAddress address = new LocalSocketAddress( 1165 daemon, LocalSocketAddress.Namespace.RESERVED); 1166 1167 // Wait for the socket to connect. 1168 while (true) { 1169 try { 1170 mSockets[i].connect(address); 1171 break; 1172 } catch (Exception e) { 1173 // ignore 1174 } 1175 checkpoint(true); 1176 } 1177 mSockets[i].setSoTimeout(500); 1178 1179 // Send over the arguments. 1180 OutputStream out = mSockets[i].getOutputStream(); 1181 for (String argument : arguments) { 1182 byte[] bytes = argument.getBytes(StandardCharsets.UTF_8); 1183 if (bytes.length >= 0xFFFF) { 1184 throw new IllegalArgumentException("Argument is too large"); 1185 } 1186 out.write(bytes.length >> 8); 1187 out.write(bytes.length); 1188 out.write(bytes); 1189 checkpoint(false); 1190 } 1191 out.write(0xFF); 1192 out.write(0xFF); 1193 out.flush(); 1194 1195 // Wait for End-of-File. 1196 InputStream in = mSockets[i].getInputStream(); 1197 while (true) { 1198 try { 1199 if (in.read() == -1) { 1200 break; 1201 } 1202 } catch (Exception e) { 1203 // ignore 1204 } 1205 checkpoint(true); 1206 } 1207 } 1208 1209 // Wait for the daemons to create the new state. 1210 while (!state.exists()) { 1211 // Check if a running daemon is dead. 1212 for (int i = 0; i < mDaemons.length; ++i) { 1213 String daemon = mDaemons[i]; 1214 if (mArguments[i] != null && !SystemService.isRunning(daemon)) { 1215 throw new IllegalStateException(daemon + " is dead"); 1216 } 1217 } 1218 checkpoint(true); 1219 } 1220 1221 // Now we are connected. Read and parse the new state. 1222 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1); 1223 if (parameters.length != 6) { 1224 throw new IllegalStateException("Cannot parse the state"); 1225 } 1226 1227 // Set the interface and the addresses in the config. 1228 mConfig.interfaze = parameters[0].trim(); 1229 1230 mConfig.addLegacyAddresses(parameters[1]); 1231 // Set the routes if they are not set in the config. 1232 if (mConfig.routes == null || mConfig.routes.isEmpty()) { 1233 mConfig.addLegacyRoutes(parameters[2]); 1234 } 1235 1236 // Set the DNS servers if they are not set in the config. 1237 if (mConfig.dnsServers == null || mConfig.dnsServers.size() == 0) { 1238 String dnsServers = parameters[3].trim(); 1239 if (!dnsServers.isEmpty()) { 1240 mConfig.dnsServers = Arrays.asList(dnsServers.split(" ")); 1241 } 1242 } 1243 1244 // Set the search domains if they are not set in the config. 1245 if (mConfig.searchDomains == null || mConfig.searchDomains.size() == 0) { 1246 String searchDomains = parameters[4].trim(); 1247 if (!searchDomains.isEmpty()) { 1248 mConfig.searchDomains = Arrays.asList(searchDomains.split(" ")); 1249 } 1250 } 1251 1252 // Here is the last step and it must be done synchronously. 1253 synchronized (Vpn.this) { 1254 // Set the start time 1255 mConfig.startTime = SystemClock.elapsedRealtime(); 1256 1257 // Check if the thread is interrupted while we are waiting. 1258 checkpoint(false); 1259 1260 // Check if the interface is gone while we are waiting. 1261 if (jniCheck(mConfig.interfaze) == 0) { 1262 throw new IllegalStateException(mConfig.interfaze + " is gone"); 1263 } 1264 1265 // Now INetworkManagementEventObserver is watching our back. 1266 mInterface = mConfig.interfaze; 1267 mVpnUsers = new ArrayList<UidRange>(); 1268 mAllowIPv4 = mConfig.allowIPv4; 1269 mAllowIPv6 = mConfig.allowIPv6; 1270 1271 agentConnect(); 1272 1273 Log.i(TAG, "Connected!"); 1274 } 1275 } catch (Exception e) { 1276 Log.i(TAG, "Aborting", e); 1277 updateState(DetailedState.FAILED, e.getMessage()); 1278 exit(); 1279 } finally { 1280 // Kill the daemons if they fail to stop. 1281 if (!initFinished) { 1282 for (String daemon : mDaemons) { 1283 SystemService.stop(daemon); 1284 } 1285 } 1286 1287 // Do not leave an unstable state. 1288 if (!initFinished || mNetworkInfo.getDetailedState() == DetailedState.CONNECTING) { 1289 agentDisconnect(); 1290 } 1291 } 1292 } 1293 1294 /** 1295 * Monitor the daemons we started, moving to disconnected state if the 1296 * underlying services fail. 1297 */ 1298 private void monitorDaemons() { 1299 if (!mNetworkInfo.isConnected()) { 1300 return; 1301 } 1302 1303 try { 1304 while (true) { 1305 Thread.sleep(2000); 1306 for (int i = 0; i < mDaemons.length; i++) { 1307 if (mArguments[i] != null && SystemService.isStopped(mDaemons[i])) { 1308 return; 1309 } 1310 } 1311 } 1312 } catch (InterruptedException e) { 1313 Log.d(TAG, "interrupted during monitorDaemons(); stopping services"); 1314 } finally { 1315 for (String daemon : mDaemons) { 1316 SystemService.stop(daemon); 1317 } 1318 1319 agentDisconnect(); 1320 } 1321 } 1322 } 1323} 1324