13d5f551cd5905c835bb789406763764a8a9a73deJason Monk/* 23d5f551cd5905c835bb789406763764a8a9a73deJason Monk * Copyright (C) 2014 The Android Open Source Project 33d5f551cd5905c835bb789406763764a8a9a73deJason Monk * 43d5f551cd5905c835bb789406763764a8a9a73deJason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 53d5f551cd5905c835bb789406763764a8a9a73deJason Monk * you may not use this file except in compliance with the License. 63d5f551cd5905c835bb789406763764a8a9a73deJason Monk * You may obtain a copy of the License at 73d5f551cd5905c835bb789406763764a8a9a73deJason Monk * 83d5f551cd5905c835bb789406763764a8a9a73deJason Monk * http://www.apache.org/licenses/LICENSE-2.0 93d5f551cd5905c835bb789406763764a8a9a73deJason Monk * 103d5f551cd5905c835bb789406763764a8a9a73deJason Monk * Unless required by applicable law or agreed to in writing, software 113d5f551cd5905c835bb789406763764a8a9a73deJason Monk * distributed under the License is distributed on an "AS IS" BASIS, 123d5f551cd5905c835bb789406763764a8a9a73deJason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133d5f551cd5905c835bb789406763764a8a9a73deJason Monk * See the License for the specific language governing permissions and 143d5f551cd5905c835bb789406763764a8a9a73deJason Monk * limitations under the License. 153d5f551cd5905c835bb789406763764a8a9a73deJason Monk */ 163d5f551cd5905c835bb789406763764a8a9a73deJason Monkpackage com.android.systemui.statusbar.policy; 173d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1824ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinekimport android.app.ActivityManager; 193d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.app.admin.DevicePolicyManager; 203d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.content.Context; 213d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.content.pm.PackageManager.NameNotFoundException; 229cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Leeimport android.content.pm.UserInfo; 233d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.net.ConnectivityManager; 243d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.net.ConnectivityManager.NetworkCallback; 253d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.net.IConnectivityManager; 2692b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monkimport android.net.Network; 273d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.net.NetworkCapabilities; 283d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.net.NetworkRequest; 293d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.os.RemoteException; 303d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.os.ServiceManager; 319cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Leeimport android.os.UserHandle; 329cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Leeimport android.os.UserManager; 333d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport android.util.Log; 349cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Leeimport android.util.SparseArray; 353d5f551cd5905c835bb789406763764a8a9a73deJason Monk 36acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggiimport com.android.internal.annotations.GuardedBy; 376795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Leeimport com.android.internal.net.LegacyVpnInfo; 383d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport com.android.internal.net.VpnConfig; 39472834518e2d23172189ee34e98c51f868628a90Robin Leeimport com.android.systemui.R; 403d5f551cd5905c835bb789406763764a8a9a73deJason Monk 413d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport java.io.FileDescriptor; 423d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport java.io.PrintWriter; 433d5f551cd5905c835bb789406763764a8a9a73deJason Monkimport java.util.ArrayList; 443d5f551cd5905c835bb789406763764a8a9a73deJason Monk 453d5f551cd5905c835bb789406763764a8a9a73deJason Monkpublic class SecurityControllerImpl implements SecurityController { 463d5f551cd5905c835bb789406763764a8a9a73deJason Monk 473d5f551cd5905c835bb789406763764a8a9a73deJason Monk private static final String TAG = "SecurityController"; 483d5f551cd5905c835bb789406763764a8a9a73deJason Monk private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 493d5f551cd5905c835bb789406763764a8a9a73deJason Monk 503d5f551cd5905c835bb789406763764a8a9a73deJason Monk private static final NetworkRequest REQUEST = new NetworkRequest.Builder() 513d5f551cd5905c835bb789406763764a8a9a73deJason Monk .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 523d5f551cd5905c835bb789406763764a8a9a73deJason Monk .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 533d5f551cd5905c835bb789406763764a8a9a73deJason Monk .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) 543d5f551cd5905c835bb789406763764a8a9a73deJason Monk .build(); 5592b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk private static final int NO_NETWORK = -1; 5692b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk 573d5f551cd5905c835bb789406763764a8a9a73deJason Monk private final Context mContext; 583d5f551cd5905c835bb789406763764a8a9a73deJason Monk private final ConnectivityManager mConnectivityManager; 599cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee private final IConnectivityManager mConnectivityManagerService; 603d5f551cd5905c835bb789406763764a8a9a73deJason Monk private final DevicePolicyManager mDevicePolicyManager; 619cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee private final UserManager mUserManager; 62acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi 63acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi @GuardedBy("mCallbacks") 64acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi private final ArrayList<SecurityControllerCallback> mCallbacks = new ArrayList<>(); 653d5f551cd5905c835bb789406763764a8a9a73deJason Monk 66472834518e2d23172189ee34e98c51f868628a90Robin Lee private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>(); 6724ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinek private int mCurrentUserId; 6863204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee private int mVpnUserId; 693d5f551cd5905c835bb789406763764a8a9a73deJason Monk 703d5f551cd5905c835bb789406763764a8a9a73deJason Monk public SecurityControllerImpl(Context context) { 713d5f551cd5905c835bb789406763764a8a9a73deJason Monk mContext = context; 723d5f551cd5905c835bb789406763764a8a9a73deJason Monk mDevicePolicyManager = (DevicePolicyManager) 733d5f551cd5905c835bb789406763764a8a9a73deJason Monk context.getSystemService(Context.DEVICE_POLICY_SERVICE); 743d5f551cd5905c835bb789406763764a8a9a73deJason Monk mConnectivityManager = (ConnectivityManager) 753d5f551cd5905c835bb789406763764a8a9a73deJason Monk context.getSystemService(Context.CONNECTIVITY_SERVICE); 769cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee mConnectivityManagerService = IConnectivityManager.Stub.asInterface( 779cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); 789cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee mUserManager = (UserManager) 799cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee context.getSystemService(Context.USER_SERVICE); 803d5f551cd5905c835bb789406763764a8a9a73deJason Monk 813d5f551cd5905c835bb789406763764a8a9a73deJason Monk // TODO: re-register network callback on user change. 823d5f551cd5905c835bb789406763764a8a9a73deJason Monk mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback); 8363204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee onUserSwitched(ActivityManager.getCurrentUser()); 843d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 853d5f551cd5905c835bb789406763764a8a9a73deJason Monk 863d5f551cd5905c835bb789406763764a8a9a73deJason Monk public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 873d5f551cd5905c835bb789406763764a8a9a73deJason Monk pw.println("SecurityController state:"); 88472834518e2d23172189ee34e98c51f868628a90Robin Lee pw.print(" mCurrentVpns={"); 89472834518e2d23172189ee34e98c51f868628a90Robin Lee for (int i = 0 ; i < mCurrentVpns.size(); i++) { 90472834518e2d23172189ee34e98c51f868628a90Robin Lee if (i > 0) { 91472834518e2d23172189ee34e98c51f868628a90Robin Lee pw.print(", "); 92472834518e2d23172189ee34e98c51f868628a90Robin Lee } 93472834518e2d23172189ee34e98c51f868628a90Robin Lee pw.print(mCurrentVpns.keyAt(i)); 94472834518e2d23172189ee34e98c51f868628a90Robin Lee pw.print('='); 95472834518e2d23172189ee34e98c51f868628a90Robin Lee pw.print(mCurrentVpns.valueAt(i).user); 96472834518e2d23172189ee34e98c51f868628a90Robin Lee } 97472834518e2d23172189ee34e98c51f868628a90Robin Lee pw.println("}"); 983d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 993d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1003d5f551cd5905c835bb789406763764a8a9a73deJason Monk @Override 101c8a5a555f1482d0f45b538eb898d6ee7e26552a6Makoto Onuki public boolean isDeviceManaged() { 102c8a5a555f1482d0f45b538eb898d6ee7e26552a6Makoto Onuki return mDevicePolicyManager.isDeviceManaged(); 1033d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 1043d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1053d5f551cd5905c835bb789406763764a8a9a73deJason Monk @Override 1063d5f551cd5905c835bb789406763764a8a9a73deJason Monk public String getDeviceOwnerName() { 107c8a5a555f1482d0f45b538eb898d6ee7e26552a6Makoto Onuki return mDevicePolicyManager.getDeviceOwnerNameOnAnyUser(); 1083d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 1093d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1103d5f551cd5905c835bb789406763764a8a9a73deJason Monk @Override 1119cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee public boolean hasProfileOwner() { 112472834518e2d23172189ee34e98c51f868628a90Robin Lee return mDevicePolicyManager.getProfileOwnerAsUser(mCurrentUserId) != null; 1133d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 1143d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1153d5f551cd5905c835bb789406763764a8a9a73deJason Monk @Override 1169cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee public String getProfileOwnerName() { 1177f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov for (int profileId : mUserManager.getProfileIdsWithDisabled(mCurrentUserId)) { 1187f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov String name = mDevicePolicyManager.getProfileOwnerNameAsUser(profileId); 1199cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee if (name != null) { 1209cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee return name; 1219cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee } 1229cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee } 1239cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee return null; 1243d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 1253d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1263d5f551cd5905c835bb789406763764a8a9a73deJason Monk @Override 127472834518e2d23172189ee34e98c51f868628a90Robin Lee public String getPrimaryVpnName() { 12863204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee VpnConfig cfg = mCurrentVpns.get(mVpnUserId); 129472834518e2d23172189ee34e98c51f868628a90Robin Lee if (cfg != null) { 13063204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee return getNameForVpnConfig(cfg, new UserHandle(mVpnUserId)); 131472834518e2d23172189ee34e98c51f868628a90Robin Lee } else { 132472834518e2d23172189ee34e98c51f868628a90Robin Lee return null; 133472834518e2d23172189ee34e98c51f868628a90Robin Lee } 134472834518e2d23172189ee34e98c51f868628a90Robin Lee } 135472834518e2d23172189ee34e98c51f868628a90Robin Lee 136472834518e2d23172189ee34e98c51f868628a90Robin Lee @Override 137472834518e2d23172189ee34e98c51f868628a90Robin Lee public String getProfileVpnName() { 1387f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) { 1397f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov if (profileId == mVpnUserId) { 140472834518e2d23172189ee34e98c51f868628a90Robin Lee continue; 141472834518e2d23172189ee34e98c51f868628a90Robin Lee } 1427f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov VpnConfig cfg = mCurrentVpns.get(profileId); 143472834518e2d23172189ee34e98c51f868628a90Robin Lee if (cfg != null) { 1447f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov return getNameForVpnConfig(cfg, UserHandle.of(profileId)); 145472834518e2d23172189ee34e98c51f868628a90Robin Lee } 146472834518e2d23172189ee34e98c51f868628a90Robin Lee } 147472834518e2d23172189ee34e98c51f868628a90Robin Lee return null; 148472834518e2d23172189ee34e98c51f868628a90Robin Lee } 149472834518e2d23172189ee34e98c51f868628a90Robin Lee 150472834518e2d23172189ee34e98c51f868628a90Robin Lee @Override 1519cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee public boolean isVpnEnabled() { 1527f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) { 1537f98aa4aa93497692f200c553d2d6fff402e3de2Fyodor Kupolov if (mCurrentVpns.get(profileId) != null) { 154472834518e2d23172189ee34e98c51f868628a90Robin Lee return true; 155472834518e2d23172189ee34e98c51f868628a90Robin Lee } 156472834518e2d23172189ee34e98c51f868628a90Robin Lee } 157472834518e2d23172189ee34e98c51f868628a90Robin Lee return false; 1583d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 1593d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1603d5f551cd5905c835bb789406763764a8a9a73deJason Monk @Override 16180d505367a5b51ea20e272e582c242ac30df3c9aRobin Lee public boolean isVpnRestricted() { 16280d505367a5b51ea20e272e582c242ac30df3c9aRobin Lee UserHandle currentUser = new UserHandle(mCurrentUserId); 16380d505367a5b51ea20e272e582c242ac30df3c9aRobin Lee return mUserManager.getUserInfo(mCurrentUserId).isRestricted() 16480d505367a5b51ea20e272e582c242ac30df3c9aRobin Lee || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, currentUser); 16580d505367a5b51ea20e272e582c242ac30df3c9aRobin Lee } 16680d505367a5b51ea20e272e582c242ac30df3c9aRobin Lee 16780d505367a5b51ea20e272e582c242ac30df3c9aRobin Lee @Override 1683128f12f216ef481b5d03892b35706cfeec26d7cJason Monk public void removeCallback(SecurityControllerCallback callback) { 169acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi synchronized (mCallbacks) { 170acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi if (callback == null) return; 171acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi if (DEBUG) Log.d(TAG, "removeCallback " + callback); 172acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi mCallbacks.remove(callback); 173acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi } 1743d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 1753d5f551cd5905c835bb789406763764a8a9a73deJason Monk 1763d5f551cd5905c835bb789406763764a8a9a73deJason Monk @Override 1773128f12f216ef481b5d03892b35706cfeec26d7cJason Monk public void addCallback(SecurityControllerCallback callback) { 178acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi synchronized (mCallbacks) { 179acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi if (callback == null || mCallbacks.contains(callback)) return; 180acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi if (DEBUG) Log.d(TAG, "addCallback " + callback); 181acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi mCallbacks.add(callback); 182acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi } 1833d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 1843d5f551cd5905c835bb789406763764a8a9a73deJason Monk 18524ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinek @Override 18624ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinek public void onUserSwitched(int newUserId) { 18724ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinek mCurrentUserId = newUserId; 1881c36315a36962321dfe870b07e28b04a1d6777e9Fyodor Kupolov final UserInfo newUserInfo = mUserManager.getUserInfo(newUserId); 1891c36315a36962321dfe870b07e28b04a1d6777e9Fyodor Kupolov if (newUserInfo.isRestricted()) { 19063204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee // VPN for a restricted profile is routed through its owner user 1911c36315a36962321dfe870b07e28b04a1d6777e9Fyodor Kupolov mVpnUserId = newUserInfo.restrictedProfileParentId; 19263204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee } else { 19363204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee mVpnUserId = mCurrentUserId; 19463204eeafe7a51953d346717639f3e6eeb1f9bd5Robin Lee } 19524ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinek fireCallbacks(); 19624ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinek } 19724ac55e658f955c330fff4bb143cfc6af37e40bfSelim Cinek 198472834518e2d23172189ee34e98c51f868628a90Robin Lee private String getNameForVpnConfig(VpnConfig cfg, UserHandle user) { 199472834518e2d23172189ee34e98c51f868628a90Robin Lee if (cfg.legacy) { 200472834518e2d23172189ee34e98c51f868628a90Robin Lee return mContext.getString(R.string.legacy_vpn_name); 201472834518e2d23172189ee34e98c51f868628a90Robin Lee } 202472834518e2d23172189ee34e98c51f868628a90Robin Lee // The package name for an active VPN is stored in the 'user' field of its VpnConfig 203472834518e2d23172189ee34e98c51f868628a90Robin Lee final String vpnPackage = cfg.user; 204472834518e2d23172189ee34e98c51f868628a90Robin Lee try { 205472834518e2d23172189ee34e98c51f868628a90Robin Lee Context userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 206472834518e2d23172189ee34e98c51f868628a90Robin Lee 0 /* flags */, user); 207472834518e2d23172189ee34e98c51f868628a90Robin Lee return VpnConfig.getVpnLabel(userContext, vpnPackage).toString(); 208472834518e2d23172189ee34e98c51f868628a90Robin Lee } catch (NameNotFoundException nnfe) { 209472834518e2d23172189ee34e98c51f868628a90Robin Lee Log.e(TAG, "Package " + vpnPackage + " is not present", nnfe); 210472834518e2d23172189ee34e98c51f868628a90Robin Lee return null; 211472834518e2d23172189ee34e98c51f868628a90Robin Lee } 212472834518e2d23172189ee34e98c51f868628a90Robin Lee } 213472834518e2d23172189ee34e98c51f868628a90Robin Lee 2143d5f551cd5905c835bb789406763764a8a9a73deJason Monk private void fireCallbacks() { 215acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi synchronized (mCallbacks) { 216acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi for (SecurityControllerCallback callback : mCallbacks) { 217acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi callback.onStateChanged(); 218acace94c1739b08ea72dc6c2f49cf29bce6c1dacJorim Jaggi } 2193d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 2203d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 2213d5f551cd5905c835bb789406763764a8a9a73deJason Monk 2223d5f551cd5905c835bb789406763764a8a9a73deJason Monk private void updateState() { 2239cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee // Find all users with an active VPN 224472834518e2d23172189ee34e98c51f868628a90Robin Lee SparseArray<VpnConfig> vpns = new SparseArray<>(); 2253d5f551cd5905c835bb789406763764a8a9a73deJason Monk try { 226472834518e2d23172189ee34e98c51f868628a90Robin Lee for (UserInfo user : mUserManager.getUsers()) { 227472834518e2d23172189ee34e98c51f868628a90Robin Lee VpnConfig cfg = mConnectivityManagerService.getVpnConfig(user.id); 2286795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee if (cfg == null) { 2296795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee continue; 2306795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee } else if (cfg.legacy) { 2316795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee // Legacy VPNs should do nothing if the network is disconnected. Third-party 2326795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee // VPN warnings need to continue as traffic can still go to the app. 2336795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee LegacyVpnInfo legacyVpn = mConnectivityManagerService.getLegacyVpnInfo(user.id); 2346795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) { 2356795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee continue; 2366795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee } 237472834518e2d23172189ee34e98c51f868628a90Robin Lee } 2386795a2aeafa6df8a5e8e3045d29991d33c8db33fRobin Lee vpns.put(user.id, cfg); 2393d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 2409cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee } catch (RemoteException rme) { 2419cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee // Roll back to previous state 2429cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee Log.e(TAG, "Unable to list active VPNs", rme); 2439cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee return; 2443d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 245472834518e2d23172189ee34e98c51f868628a90Robin Lee mCurrentVpns = vpns; 2463d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 2473d5f551cd5905c835bb789406763764a8a9a73deJason Monk 2483d5f551cd5905c835bb789406763764a8a9a73deJason Monk private final NetworkCallback mNetworkCallback = new NetworkCallback() { 24992b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk @Override 25092b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk public void onAvailable(Network network) { 2519cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee if (DEBUG) Log.d(TAG, "onAvailable " + network.netId); 2529cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee updateState(); 2539cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee fireCallbacks(); 25492b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk }; 25592b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk 25692b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk // TODO Find another way to receive VPN lost. This may be delayed depending on 25792b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk // how long the VPN connection is held on to. 25892b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk @Override 25992b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk public void onLost(Network network) { 26092b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk if (DEBUG) Log.d(TAG, "onLost " + network.netId); 2619cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee updateState(); 2629cb1d5f6418da8cecdee58114c6e97b80c1b153fRobin Lee fireCallbacks(); 26392b5c8196b7cff36a8dc0431a30c014e0467c7cfJason Monk }; 2643d5f551cd5905c835bb789406763764a8a9a73deJason Monk }; 2653d5f551cd5905c835bb789406763764a8a9a73deJason Monk} 266